HHH-7616 - Integrate hibernate-tools JDBCBinder into hibernate-orm

This commit is contained in:
Steve Ebersole 2012-09-28 10:53:58 -05:00
parent 9914b17010
commit 5dd5e251ba
30 changed files with 1150 additions and 632 deletions

View File

@ -179,11 +179,11 @@ public class Identifier {
Identifier that = (Identifier) o;
return isQuoted == that.isQuoted
&& text.equals( that.text );
&& isQuoted ? text.equals( that.text ) : text.equalsIgnoreCase( that.text );
}
@Override
public int hashCode() {
return text.hashCode();
return isQuoted ? text.hashCode() : text.toUpperCase().hashCode();
}
}

View File

@ -31,8 +31,8 @@ import java.util.Set;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.tool.schema.spi.ColumnInformation;
import org.hibernate.tool.schema.spi.TableInformation;
import org.hibernate.tool.schema.extract.spi.ColumnInformation;
import org.hibernate.tool.schema.extract.spi.TableInformation;
/**
* Models the concept of a relational <tt>TABLE</tt> (or <tt>VIEW</tt>).
@ -201,7 +201,7 @@ public class Table extends AbstractTableSpecification implements Exportable {
}
final Column column = (Column) value;
final ColumnInformation columnInformation = tableInformation.getColumnInformation( column.getColumnName() );
final ColumnInformation columnInformation = tableInformation.getColumn( column.getColumnName() );
if ( columnInformation != null ) {
continue;

View File

@ -21,12 +21,12 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.internal;
package org.hibernate.tool.schema.extract.internal;
import org.hibernate.TruthValue;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.tool.schema.spi.ColumnInformation;
import org.hibernate.tool.schema.spi.TableInformation;
import org.hibernate.tool.schema.extract.spi.ColumnInformation;
import org.hibernate.tool.schema.extract.spi.TableInformation;
/**
* JDBC column metadata

View File

@ -0,0 +1,77 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.extract.internal;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.tool.schema.extract.spi.DatabaseInformation;
import org.hibernate.tool.schema.extract.spi.ExtractionContext;
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
import org.hibernate.tool.schema.extract.spi.TableInformation;
/**
* @author Steve Ebersole
*/
public class DatabaseInformationImpl implements DatabaseInformation, ExtractionContext.RegisteredObjectAccess {
private final Map<ObjectName,TableInformation> tables = new HashMap<ObjectName, TableInformation>();
private final Map<ObjectName,SequenceInformation> sequences = new HashMap<ObjectName, SequenceInformation>();
public DatabaseInformationImpl() {
}
// DatabaseInformation implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public TableInformation getTableInformation(ObjectName tableName) {
return locateRegisteredTableInformation( tableName );
}
@Override
public SequenceInformation getSequenceInformation(ObjectName sequenceName) {
return locateRegisteredSequenceInformation( sequenceName );
}
// RegisteredObjectAccess implementation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@Override
public TableInformation locateRegisteredTableInformation(ObjectName tableName) {
return tables.get( tableName );
}
public void registerTableInformation(TableInformation tableInformation) {
tables.put( tableInformation.getName(), tableInformation );
}
@Override
public SequenceInformation locateRegisteredSequenceInformation(ObjectName sequenceName) {
return sequences.get( sequenceName );
}
public void registerSequenceInformation(SequenceInformation sequenceInformation) {
sequences.put( sequenceInformation.getSequenceName(), sequenceInformation );
}
}

View File

@ -0,0 +1,103 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.extract.internal;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.tool.schema.extract.spi.ExtractionContext;
/**
* @author Steve Ebersole
*/
public class ExtractionContextImpl implements ExtractionContext {
private final JdbcEnvironment jdbcEnvironment;
private final JdbcConnectionAccess jdbcConnectionAccess;
private final RegisteredObjectAccess registeredTableAccess;
private Connection jdbcConnection;
private DatabaseMetaData jdbcDatabaseMetaData;
public ExtractionContextImpl(
JdbcEnvironment jdbcEnvironment,
JdbcConnectionAccess jdbcConnectionAccess,
RegisteredObjectAccess registeredTableAccess) {
this.jdbcEnvironment = jdbcEnvironment;
this.jdbcConnectionAccess = jdbcConnectionAccess;
this.registeredTableAccess = registeredTableAccess;
}
@Override
public JdbcEnvironment getJdbcEnvironment() {
return jdbcEnvironment;
}
@Override
public Connection getJdbcConnection() {
if ( jdbcConnection == null ) {
try {
jdbcConnection = jdbcConnectionAccess.obtainConnection();
}
catch (SQLException e) {
throw jdbcEnvironment.getSqlExceptionHelper().convert( e, "Unable to obtain JDBC Connection" );
}
}
return jdbcConnection;
}
@Override
public DatabaseMetaData getJdbcDatabaseMetaData() {
if ( jdbcDatabaseMetaData == null ) {
try {
jdbcDatabaseMetaData = getJdbcConnection().getMetaData();
}
catch (SQLException e) {
throw jdbcEnvironment.getSqlExceptionHelper().convert( e, "Unable to obtain JDBC DatabaseMetaData" );
}
}
return jdbcDatabaseMetaData;
}
@Override
public RegisteredObjectAccess getRegisteredObjectAccess() {
return registeredTableAccess;
}
public void cleanup() {
if ( jdbcDatabaseMetaData != null ) {
jdbcDatabaseMetaData = null;
}
if ( jdbcConnection != null ) {
try {
jdbcConnectionAccess.releaseConnection( jdbcConnection );
}
catch (SQLException ignore) {
}
}
}
}

View File

@ -21,15 +21,13 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.internal;
package org.hibernate.tool.schema.extract.internal;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.tool.schema.spi.ColumnInformation;
import org.hibernate.tool.schema.spi.ForeignKeyInformation;
import org.hibernate.tool.schema.spi.SchemaManagementException;
import org.hibernate.tool.schema.extract.spi.ColumnInformation;
import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation;
/**
* @author Steve Ebersole
@ -38,7 +36,7 @@ public class ForeignKeyInformationImpl implements ForeignKeyInformation {
private final Identifier fkIdentifier;
private final List<ColumnReferenceMapping> columnMappingList;
private ForeignKeyInformationImpl(
public ForeignKeyInformationImpl(
Identifier fkIdentifier,
List<ColumnReferenceMapping> columnMappingList) {
this.fkIdentifier = fkIdentifier;
@ -51,38 +49,10 @@ public class ForeignKeyInformationImpl implements ForeignKeyInformation {
}
@Override
public List<ColumnReferenceMapping> getColumnReferenceMappingList() {
public Iterable<ColumnReferenceMapping> getColumnReferenceMappings() {
return columnMappingList;
}
public static Builder builder(Identifier fkIdentifier) {
return new Builder( fkIdentifier );
}
public static class Builder {
private final Identifier fkIdentifier;
private final List<ColumnReferenceMapping> columnMappingList = new ArrayList<ColumnReferenceMapping>();
public Builder(Identifier fkIdentifier) {
this.fkIdentifier = fkIdentifier;
}
public Builder addColumnMapping(ColumnInformation referencing, ColumnInformation referenced) {
columnMappingList.add( new ColumnReferenceMappingImpl( referencing, referenced ) );
return this;
}
public ForeignKeyInformationImpl build() {
if ( columnMappingList.isEmpty() ) {
throw new SchemaManagementException(
"Attempt to resolve foreign key metadata from JDBC metadata failed to find " +
"column mappings for foreign key named [" + fkIdentifier.getText() + "]"
);
}
return new ForeignKeyInformationImpl( fkIdentifier, columnMappingList );
}
}
public static class ColumnReferenceMappingImpl implements ColumnReferenceMapping {
private final ColumnInformation referencing;
private final ColumnInformation referenced;

View File

@ -21,15 +21,15 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.internal;
package org.hibernate.tool.schema.extract.internal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.tool.schema.spi.ColumnInformation;
import org.hibernate.tool.schema.spi.IndexInformation;
import org.hibernate.tool.schema.extract.spi.ColumnInformation;
import org.hibernate.tool.schema.extract.spi.IndexInformation;
import org.hibernate.tool.schema.spi.SchemaManagementException;
/**

View File

@ -21,10 +21,10 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.internal;
package org.hibernate.tool.schema.extract.internal;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.tool.schema.spi.SequenceInformation;
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
/**
* For now we only collect sequence name. If all databases support it, would really like to see INCREMENT here as well.

View File

@ -0,0 +1,347 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.extract.internal;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.StringTokenizer;
import org.hibernate.JDBCException;
import org.hibernate.TruthValue;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.tool.schema.extract.spi.ColumnInformation;
import org.hibernate.tool.schema.extract.spi.ExtractionContext;
import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation;
import org.hibernate.tool.schema.extract.spi.IndexInformation;
import org.hibernate.tool.schema.extract.spi.SchemaMetaDataExtractor;
import org.hibernate.tool.schema.extract.spi.TableInformation;
import org.hibernate.tool.schema.spi.SchemaManagementException;
/**
* Implementation of the SchemaMetaDataExtractor contract which uses the standard JDBC {@link java.sql.DatabaseMetaData}
* API for extraction.
*
* @author Steve Ebersole
*/
public class StandardJdbcDatabaseMetaDataExtractor implements SchemaMetaDataExtractor {
private static final String[] TABLE_TYPES = new String[] { "TABLE", "VIEW" };
private final ExtractionContext extractionContext;
public StandardJdbcDatabaseMetaDataExtractor(ExtractionContext extractionContext) {
this.extractionContext = extractionContext;
}
protected IdentifierHelper identifierHelper() {
return extractionContext.getJdbcEnvironment().getIdentifierHelper();
}
protected JDBCException convertSQLException(SQLException sqlException, String message) {
return extractionContext.getJdbcEnvironment().getSqlExceptionHelper().convert( sqlException, message );
}
@Override
public Iterable<TableInformation> getTables(String catalogFilter, String schemaFilter) {
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getTables(
catalogFilter,
schemaFilter,
null,
TABLE_TYPES
);
final List<TableInformation> results = new ArrayList<TableInformation>();
try {
while ( resultSet.next() ) {
final Identifier catalogIdentifier = identifierHelper().fromMetaDataCatalogName(
resultSet.getString(
"TABLE_CAT"
)
);
final Identifier schemaIdentifier = identifierHelper().fromMetaDataSchemaName(
resultSet.getString(
"TABLE_SCHEM"
)
);
final Identifier tableIdentifier = identifierHelper().fromMetaDataObjectName(
resultSet.getString(
"TABLE_NAME"
)
);
final ObjectName tableName = new ObjectName( catalogIdentifier, schemaIdentifier, tableIdentifier );
TableInformation tableInformation = new TableInformationImpl(
this,
tableName,
isPhysicalTableType( resultSet.getString( "TABLE_TYPE" ) ),
resultSet.getString( "REMARKS" )
);
results.add( tableInformation );
}
}
finally {
try {
resultSet.close();
}
catch (SQLException ignore) {
}
}
return results;
}
catch (SQLException sqlException) {
throw convertSQLException( sqlException, "Error accessing table metadata" );
}
}
protected boolean isPhysicalTableType(String tableType) {
return "TABLE".equalsIgnoreCase( tableType );
}
@Override
public Iterable<ColumnInformation> getColumns(TableInformation tableInformation) {
final List<ColumnInformation> results = new ArrayList<ColumnInformation>();
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getColumns(
identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ),
identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ),
identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ),
"%"
);
try {
while ( resultSet.next() ) {
final String columnName = resultSet.getString( "COLUMN_NAME" );
if ( columnName == null ) {
continue;
}
results.add(
new ColumnInformationImpl(
tableInformation,
Identifier.toIdentifier( columnName ),
resultSet.getInt( "DATA_TYPE" ),
new StringTokenizer( resultSet.getString( "TYPE_NAME" ), "() " ).nextToken(),
resultSet.getInt( "COLUMN_SIZE" ),
resultSet.getInt("DECIMAL_DIGITS"),
interpretTruthValue( resultSet.getString( "IS_NULLABLE" ) )
)
);
}
}
finally {
resultSet.close();
}
}
catch (SQLException e) {
throw convertSQLException( e, "Error accessing column metadata: " + tableInformation.getName().toString() );
}
return results;
}
private TruthValue interpretTruthValue(String nullable) {
if ( "yes".equalsIgnoreCase( nullable ) ) {
return TruthValue.TRUE;
}
else if ( "no".equalsIgnoreCase( nullable ) ) {
return TruthValue.FALSE;
}
return TruthValue.UNKNOWN;
}
@Override
public Iterable<IndexInformation> getIndexes(TableInformation tableInformation) {
final Map<Identifier, IndexInformationImpl.Builder> builders = new HashMap<Identifier, IndexInformationImpl.Builder>();
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getIndexInfo(
identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ),
identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ),
identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ),
false, // DO NOT limit to just unique
true // DO require up-to-date results
);
try {
while ( resultSet.next() ) {
if ( resultSet.getShort("TYPE") == DatabaseMetaData.tableIndexStatistic ) {
continue;
}
final Identifier indexIdentifier = Identifier.toIdentifier( resultSet.getString( "INDEX_NAME" ) );
IndexInformationImpl.Builder builder = builders.get( indexIdentifier );
if ( builder == null ) {
builder = IndexInformationImpl.builder( indexIdentifier );
builders.put( indexIdentifier, builder );
}
final Identifier columnIdentifier = Identifier.toIdentifier( resultSet.getString( "COLUMN_NAME" ) );
final ColumnInformation columnInformation = tableInformation.getColumn( columnIdentifier );
if ( columnInformation == null ) {
throw new SchemaManagementException(
"Could not locate column information using identifier [" + columnIdentifier.getText() + "]"
);
}
builder.addColumn( columnInformation );
}
}
finally {
resultSet.close();
}
}
catch (SQLException e) {
throw convertSQLException(
e,
"Error accessing index information: " + tableInformation.getName().toString()
);
}
final List<IndexInformation> indexes = new ArrayList<IndexInformation>();
for ( IndexInformationImpl.Builder builder : builders.values() ) {
IndexInformationImpl index = builder.build();
indexes.add( index );
}
return indexes;
}
@Override
public Iterable<ForeignKeyInformation> getForeignKeys(TableInformation tableInformation) {
final Map<Identifier, ForeignKeyBuilder> fkBuilders = new HashMap<Identifier, ForeignKeyBuilder>();
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getImportedKeys(
identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ),
identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ),
identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() )
);
// todo : need to account for getCrossReference() as well...
try {
while ( resultSet.next() ) {
// IMPL NOTE : The builder is mainly used to collect the column reference mappings
final Identifier fkIdentifier = Identifier.toIdentifier( resultSet.getString( "FK_NAME" ) );
ForeignKeyBuilder fkBuilder = fkBuilders.get( fkIdentifier );
if ( fkBuilder == null ) {
fkBuilder = generateForeignKeyBuilder( fkIdentifier );
fkBuilders.put( fkIdentifier, fkBuilder );
}
final ObjectName incomingPkTableName = extractKeyTableName( resultSet, "PK" );
final TableInformation pkTableInformation = extractionContext.getRegisteredObjectAccess()
.locateRegisteredTableInformation( incomingPkTableName );
if ( pkTableInformation == null ) {
// the assumption here is that we have not seen this table already based on fully-qualified name
// during previous step of building all table metadata so most likely this is
// not a match based solely on schema/catalog and that another row in this result set
// should match.
continue;
}
final Identifier fkColumnIdentifier = Identifier.toIdentifier( resultSet.getString( "FKCOLUMN_NAME" ) );
final Identifier pkColumnIdentifier = Identifier.toIdentifier( resultSet.getString( "PKCOLUMN_NAME" ) );
fkBuilder.addColumnMapping(
tableInformation.getColumn( fkColumnIdentifier ),
pkTableInformation.getColumn( pkColumnIdentifier )
);
}
}
finally {
resultSet.close();
}
}
catch (SQLException e) {
throw convertSQLException(
e,
"Error accessing column metadata: " + tableInformation.getName().toString()
);
}
final List<ForeignKeyInformation> fks = new ArrayList<ForeignKeyInformation>();
for ( ForeignKeyBuilder fkBuilder : fkBuilders.values() ) {
ForeignKeyInformation fk = fkBuilder.build();
fks.add( fk );
}
return fks;
}
private ForeignKeyBuilder generateForeignKeyBuilder(Identifier fkIdentifier) {
return new ForeignKeyBuilderImpl( fkIdentifier );
}
protected static interface ForeignKeyBuilder {
public ForeignKeyBuilder addColumnMapping(ColumnInformation referencing, ColumnInformation referenced);
public ForeignKeyInformation build();
}
protected static class ForeignKeyBuilderImpl implements ForeignKeyBuilder {
private final Identifier fkIdentifier;
private final List<ForeignKeyInformation.ColumnReferenceMapping> columnMappingList = new ArrayList<ForeignKeyInformation.ColumnReferenceMapping>();
public ForeignKeyBuilderImpl(Identifier fkIdentifier) {
this.fkIdentifier = fkIdentifier;
}
@Override
public ForeignKeyBuilder addColumnMapping(ColumnInformation referencing, ColumnInformation referenced) {
columnMappingList.add( new ForeignKeyInformationImpl.ColumnReferenceMappingImpl( referencing, referenced ) );
return this;
}
@Override
public ForeignKeyInformationImpl build() {
if ( columnMappingList.isEmpty() ) {
throw new SchemaManagementException(
"Attempt to resolve foreign key metadata from JDBC metadata failed to find " +
"column mappings for foreign key named [" + fkIdentifier.getText() + "]"
);
}
return new ForeignKeyInformationImpl( fkIdentifier, columnMappingList );
}
}
private ObjectName extractKeyTableName(ResultSet resultSet, String prefix) throws SQLException {
final String incomingCatalogName = resultSet.getString( prefix + "TABLE_SCHEM" );
final String incomingSchemaName = resultSet.getString( prefix + "TABLE_CATALOG" );
final String incomingTableName = resultSet.getString( prefix + "TABLE_NAME" );
return new ObjectName(
Identifier.toIdentifier( incomingCatalogName ), Identifier.toIdentifier( incomingSchemaName ),
Identifier.toIdentifier( incomingTableName )
);
}
}

View File

@ -0,0 +1,150 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.extract.internal;
import java.util.HashMap;
import java.util.Map;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.tool.schema.extract.spi.ColumnInformation;
import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation;
import org.hibernate.tool.schema.extract.spi.IndexInformation;
import org.hibernate.tool.schema.extract.spi.SchemaMetaDataExtractor;
import org.hibernate.tool.schema.extract.spi.TableInformation;
/**
* Provides access to information about existing schema objects (tables, sequences etc) of existing database.
*
* @author Christoph Sturm
* @author Max Rydahl Andersen
* @author Steve Ebersole
*/
public class TableInformationImpl implements TableInformation {
private final SchemaMetaDataExtractor metaDataExtractor;
private final ObjectName tableName;
private final boolean physicalTable;
private final String comment;
private Map<Identifier, ColumnInformation> columns;
private Map<Identifier, ForeignKeyInformation> foreignKeys;
private Map<Identifier, IndexInformation> indexes;
public TableInformationImpl(
SchemaMetaDataExtractor metaDataExtractor,
ObjectName tableName,
boolean physicalTable,
String comment) {
this.metaDataExtractor = metaDataExtractor;
this.tableName = tableName;
this.physicalTable = physicalTable;
this.comment = comment;
}
@Override
public ObjectName getName() {
return tableName;
}
@Override
public boolean isPhysicalTable() {
return physicalTable;
}
@Override
public String getComment() {
return comment;
}
@Override
public Iterable<ColumnInformation> getColumns() {
return columns().values();
}
protected Map<Identifier, ColumnInformation> columns() {
if ( this.columns == null ) {
final Map<Identifier, ColumnInformation> columnMap = new HashMap<Identifier, ColumnInformation>();
final Iterable<ColumnInformation> columnInformationItr = metaDataExtractor.getColumns( this );
for ( ColumnInformation columnInformation : columnInformationItr ) {
columnMap.put( columnInformation.getColumnIdentifier(), columnInformation );
}
this.columns = columnMap;
}
return this.columns;
}
@Override
public ColumnInformation getColumn(Identifier columnIdentifier) {
return columns().get( columnIdentifier );
}
@Override
public Iterable<ForeignKeyInformation> getForeignKeys() {
return foreignKeys().values();
}
protected Map<Identifier, ForeignKeyInformation> foreignKeys() {
if ( foreignKeys == null ) {
final Map<Identifier, ForeignKeyInformation> fkMap = new HashMap<Identifier, ForeignKeyInformation>();
final Iterable<ForeignKeyInformation> fks = metaDataExtractor.getForeignKeys( this );
for ( ForeignKeyInformation fk : fks ) {
fkMap.put( fk.getForeignKeyIdentifier(), fk );
}
this.foreignKeys = fkMap;
}
return foreignKeys;
}
@Override
public ForeignKeyInformation getForeignKey(Identifier fkIdentifier) {
return foreignKeys().get( fkIdentifier );
}
@Override
public Iterable<IndexInformation> getIndexes() {
return indexes().values();
}
protected Map<Identifier, IndexInformation> indexes() {
if ( indexes == null ) {
final Map<Identifier, IndexInformation> indexMap = new HashMap<Identifier, IndexInformation>();
final Iterable<IndexInformation> indexes = metaDataExtractor.getIndexes( this );
for ( IndexInformation index : indexes ) {
indexMap.put( index.getIndexIdentifier(), index );
}
this.indexes = indexMap;
}
return indexes;
}
@Override
public IndexInformation getIndex(Identifier indexName) {
return indexes().get( indexName );
}
@Override
public String toString() {
return "TableInformationImpl(" + tableName.toString() + ')';
}
}

View File

@ -21,19 +21,19 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.internal;
package org.hibernate.tool.schema.extract.internal;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.tool.schema.spi.SequenceInformation;
import org.hibernate.tool.schema.spi.SequenceInformationExtractor;
import org.hibernate.tool.schema.extract.spi.ExtractionContext;
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
import org.hibernate.tool.schema.extract.spi.SequenceInformationExtractor;
/**
* Temporary implementation that works for H2.
@ -41,15 +41,10 @@ import org.hibernate.tool.schema.spi.SequenceInformationExtractor;
* @author Steve Ebersole
*/
public class TemporarySequenceInformationExtractor implements SequenceInformationExtractor {
private final JdbcEnvironment jdbcEnvironment;
public TemporarySequenceInformationExtractor(JdbcEnvironment jdbcEnvironment) {
this.jdbcEnvironment = jdbcEnvironment;
}
@Override
public Iterable<SequenceInformation> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException {
Statement statement = databaseMetaData.getConnection().createStatement();
public Iterable<SequenceInformation> extractMetadata(ExtractionContext extractionContext) throws SQLException {
final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper();
final Statement statement = extractionContext.getJdbcConnection().createStatement();
try {
ResultSet resultSet = statement.executeQuery(
"select SEQUENCE_CATALOG, SEQUENCE_SCHEMA, SEQUENCE_NAME, INCREMENT " +
@ -61,20 +56,14 @@ public class TemporarySequenceInformationExtractor implements SequenceInformatio
sequenceInformationList.add(
new SequenceInformationImpl(
new ObjectName(
jdbcEnvironment.getIdentifierHelper().fromMetaDataCatalogName(
resultSet.getString(
"SEQUENCE_CATALOG"
)
identifierHelper.fromMetaDataCatalogName(
resultSet.getString( "SEQUENCE_CATALOG" )
),
jdbcEnvironment.getIdentifierHelper().fromMetaDataSchemaName(
resultSet.getString(
"SEQUENCE_SCHEMA"
)
identifierHelper.fromMetaDataSchemaName(
resultSet.getString( "SEQUENCE_SCHEMA" )
),
jdbcEnvironment.getIdentifierHelper().fromMetaDataCatalogName(
resultSet.getString(
"SEQUENCE_NAME"
)
identifierHelper.fromMetaDataCatalogName(
resultSet.getString( "SEQUENCE_NAME" )
)
),
resultSet.getInt( "INCREMENT" )

View File

@ -0,0 +1,28 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.extract;
/**
* Defines a model of schema information extracted from the database through JDBC.
*/

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.spi;
package org.hibernate.tool.schema.extract.spi;
import org.hibernate.TruthValue;
import org.hibernate.metamodel.spi.relational.Identifier;

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.spi;
package org.hibernate.tool.schema.extract.spi;
import org.hibernate.metamodel.spi.relational.ObjectName;

View File

@ -0,0 +1,142 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.extract.spi;
import java.sql.Connection;
import java.sql.SQLException;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.Schema;
import org.hibernate.tool.schema.extract.internal.DatabaseInformationImpl;
import org.hibernate.tool.schema.extract.internal.ExtractionContextImpl;
import org.hibernate.tool.schema.extract.internal.StandardJdbcDatabaseMetaDataExtractor;
import org.hibernate.tool.schema.extract.internal.TemporarySequenceInformationExtractor;
/**
* Acts as the entry point into building {@link DatabaseInformation} instances. The correlation is 1-to-1 between
* DatabaseInformationBuilder and DatabaseInformation, meaning a given DatabaseInformationBuilder should only be used
* to build a single DatabaseInformation instance.
*
* @author Steve Ebersole
*/
public class DatabaseInformationBuilder {
private final DatabaseInformationImpl databaseInformation;
private final ExtractionContext extractionContext;
private final SchemaMetaDataExtractor metaDataExtractor;
public DatabaseInformationBuilder(JdbcEnvironment jdbcEnvironment, final Connection jdbcConnection) {
this(
jdbcEnvironment,
new JdbcConnectionAccess() {
@Override
public Connection obtainConnection() throws SQLException {
return jdbcConnection;
}
@Override
public void releaseConnection(Connection connection) throws SQLException {
// nothing to do, we don't "own" the connection
}
@Override
public boolean supportsAggressiveRelease() {
return false;
}
}
);
}
public DatabaseInformationBuilder(JdbcEnvironment jdbcEnvironment, JdbcConnectionAccess jdbcConnectionAccess) {
this.databaseInformation = new DatabaseInformationImpl();
this.extractionContext = new ExtractionContextImpl( jdbcEnvironment, jdbcConnectionAccess, databaseInformation );
// todo : make this pluggable...
metaDataExtractor = new StandardJdbcDatabaseMetaDataExtractor( extractionContext );
}
public DatabaseInformationBuilder prepareAll() {
return prepare( SchemaMetaDataExtractor.ALL_CATALOGS_FILTER, SchemaMetaDataExtractor.ALL_SCHEMAS_FILTER );
}
public DatabaseInformationBuilder prepareCatalogAndSchema(Schema.Name schemaName) {
final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper();
return prepare(
identifierHelper.toMetaDataCatalogName( schemaName.getCatalog() ),
identifierHelper.toMetaDataSchemaName( schemaName.getSchema() )
);
}
public DatabaseInformationBuilder prepareCatalog(Identifier catalog) {
final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper();
return prepare(
identifierHelper.toMetaDataCatalogName( catalog ),
SchemaMetaDataExtractor.ALL_SCHEMAS_FILTER
);
}
public DatabaseInformationBuilder prepareSchema(Identifier schema) {
final IdentifierHelper identifierHelper = extractionContext.getJdbcEnvironment().getIdentifierHelper();
return prepare(
SchemaMetaDataExtractor.ALL_CATALOGS_FILTER,
identifierHelper.toMetaDataSchemaName( schema )
);
}
private DatabaseInformationBuilder prepare(String catalog, String schema) {
// todo : apply filtering
for ( TableInformation tableInformation : metaDataExtractor.getTables( catalog, schema ) ) {
databaseInformation.registerTableInformation( tableInformation );
}
final Iterable<SequenceInformation> sequences = extractSequences();
if ( sequences != null ) {
for ( SequenceInformation sequenceInformation : sequences ) {
databaseInformation.registerSequenceInformation( sequenceInformation );
}
}
return this;
}
private Iterable<SequenceInformation> extractSequences() {
// todo : temporary impl!!!
final TemporarySequenceInformationExtractor seqExtractor = new TemporarySequenceInformationExtractor();
try {
return seqExtractor.extractMetadata( extractionContext );
}
catch (SQLException e) {
throw extractionContext.getJdbcEnvironment().getSqlExceptionHelper().convert( e, "Unable to access sequence information" );
}
}
public DatabaseInformation build() {
return databaseInformation;
}
}

View File

@ -0,0 +1,50 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.extract.spi;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import org.hibernate.engine.jdbc.connections.spi.JdbcConnectionAccess;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.metamodel.spi.relational.ObjectName;
/**
* Defines a context for performing extraction including providing access to information about ongoing extraction as
* well as to delegates needed in performing extraction.
*
* @author Steve Ebersole
*/
public interface ExtractionContext {
public JdbcEnvironment getJdbcEnvironment();
public Connection getJdbcConnection();
public DatabaseMetaData getJdbcDatabaseMetaData();
public static interface RegisteredObjectAccess {
public TableInformation locateRegisteredTableInformation(ObjectName tableName);
public SequenceInformation locateRegisteredSequenceInformation(ObjectName sequenceName);
}
public RegisteredObjectAccess getRegisteredObjectAccess();
}

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.spi;
package org.hibernate.tool.schema.extract.spi;
import java.util.List;
@ -39,11 +39,11 @@ public interface ForeignKeyInformation {
public Identifier getForeignKeyIdentifier();
/**
* Get the list of column mappings that define the reference.
* Get the column mappings that define the reference. Returned in sequential order.
*
* @return The mapping list
* @return The sequential column reference mappings.
*/
public List<ColumnReferenceMapping> getColumnReferenceMappingList();
public Iterable<ColumnReferenceMapping> getColumnReferenceMappings();
public static interface ColumnReferenceMapping {
/**

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.spi;
package org.hibernate.tool.schema.extract.spi;
import java.util.List;

View File

@ -0,0 +1,42 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.extract.spi;
import org.hibernate.metamodel.spi.relational.Identifier;
/**
* Provides access to information about existing primary key for a table
*
* @author Steve Ebersole
*/
public interface PrimaryKeyInformation {
/**
* Obtain the identifier for this PK.
*
* @return The PK identifier.
*/
public Identifier getPrimaryKeyIdentifier();
public Iterable<ColumnInformation> getColumns();
}

View File

@ -0,0 +1,107 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.extract.spi;
import java.util.Map;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.tool.schema.extract.internal.ForeignKeyInformationImpl;
import org.hibernate.tool.schema.extract.internal.IndexInformationImpl;
import org.hibernate.tool.schema.extract.internal.TableInformationImpl;
/**
* Contract for extracting information about objects in the database schema(s). To an extent, the contract largely
* mirrors parts of the JDBC {@link java.sql.DatabaseMetaData} contract. THe intention is to insulate callers
* from {@link java.sql.DatabaseMetaData} since on many databases there are better ways to get information from
* the meta schema.
*
* NOTE : Concepts here taken largely from the {@code MetaDataDialect} class Hibernate Tools.
*
* @author Steve Ebersole
*/
public interface SchemaMetaDataExtractor {
public static final String ALL_CATALOGS_FILTER = null;
public static final String SANS_CATALOG_FILTER = "";
public static final String ALL_SCHEMAS_FILTER = null;
public static final String SANS_SCHEMA_FILTER = "";
/**
* Return information about all matching tables
*
* @param catalogFilter Filter to be applied for the catalog to which tables belong. Can be either the
* name of the catalog to match or one of 2 special values:<ol>
* <li>
* {@code null} ({@link #ALL_CATALOGS_FILTER}) - Indicates that tables from all catalogs should be returned
* </li>
* <li>
* {@code ""} (empty String) ({@link #SANS_CATALOG_FILTER}) - Indicates that only tables without a catalog
* should be returned
* </li>
* </ol>
* @param schemaFilter Filter to be applied for the schema to which tables belong. Can be either the
* name of the schema to match or one of 2 special values:<ol>
* <li>
* {@code null} ({@link #ALL_SCHEMAS_FILTER}) - Indicates that tables from all schemas should be returned
* </li>
* <li>
* {@code ""} (empty String) ({@link #SANS_SCHEMA_FILTER}) - Indicates that only tables without a schema
* should be returned
* </li>
* </ol>
*
* @return iterator with map elements that has "TABLE_NAME", "TABLE_SCHEMA", "TABLE_CAT", "TABLE_TYPE" keys.
*/
public Iterable<TableInformation> getTables(String catalogFilter, String schemaFilter);
/**
* Return information about columns for the given table. Typically called from the TableInformation itself
* as part of on-demand initialization of its state.
*
* @param tableInformation The table for which to locate columns
*
* @return The extracted column information
*/
public Iterable<ColumnInformation> getColumns(TableInformation tableInformation);
/**
* Extract information about indexes defined against the given table. Typically called from the TableInformation
* itself as part of on-demand initialization of its state.
*
* @param tableInformation The table for which to locate indexes
*
* @return The extracted index information
*/
public Iterable<IndexInformation> getIndexes(TableInformation tableInformation);
/**
* Extract information about foreign keys defined on the given table (targeting or point-at other tables).
* Typically called from the TableInformation itself as part of on-demand initialization of its state.
*
* @param tableInformation The table for which to locate foreign-keys
*
* @return The extracted foreign-key information
*/
public Iterable<ForeignKeyInformation> getForeignKeys(TableInformation tableInformation);
}

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.spi;
package org.hibernate.tool.schema.extract.spi;
import org.hibernate.metamodel.spi.relational.ObjectName;

View File

@ -21,9 +21,8 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.spi;
package org.hibernate.tool.schema.extract.spi;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
/**
@ -36,12 +35,12 @@ public interface SequenceInformationExtractor {
/**
* Get the information about sequences.
*
* @param databaseMetaData The JDBC DatabaseMetadata
* @param extractionContext Access to resources needed to perform the extraction
*
* @return The extracted information about existing sequences.
*
* @throws SQLException Don't bother handling SQLExceptions (unless you want to), we will deal with them in the
* caller.
*/
public Iterable<SequenceInformation> extractMetadata(DatabaseMetaData databaseMetaData) throws SQLException;
public Iterable<SequenceInformation> extractMetadata(ExtractionContext extractionContext) throws SQLException;
}

View File

@ -21,7 +21,7 @@
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.spi;
package org.hibernate.tool.schema.extract.spi;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
@ -41,6 +41,27 @@ public interface TableInformation {
*/
public ObjectName getName();
/**
* Does this information describe a physical table as opposed to a view, etc?
*
* @return {@code true} if this is a physical table; {@code false} otherwise.
*/
public boolean isPhysicalTable();
/**
* Get the comments/remarks defined for the table.
*
* @return The table comments
*/
public String getComment();
/**
* Get an iterable over all of the table's columns.
*
* @return All of the table's columns
*/
public Iterable<ColumnInformation> getColumns();
/**
* Retrieve the named ColumnInformation
*
@ -48,7 +69,14 @@ public interface TableInformation {
*
* @return The matching column information. May return {@code null}
*/
public ColumnInformation getColumnInformation(Identifier columnIdentifier);
public ColumnInformation getColumn(Identifier columnIdentifier);
/**
* Obtain an iterable over all the table's defined foreign keys.
*
* @return The iterable.
*/
public Iterable<ForeignKeyInformation> getForeignKeys();
/**
* Retrieve the named ForeignKeyInformation
@ -57,17 +85,17 @@ public interface TableInformation {
*
* @return The matching foreign key information. May return {@code null}
*/
public ForeignKeyInformation getForeignKeyInformation(Identifier keyName);
public ForeignKeyInformation getForeignKey(Identifier keyName);
/**
* Obtain an iterable over all the table's defined foreign keys.
* Obtain an iterable over all the table's defined indexes.
*
* @return The iterable.
*/
public Iterable<ForeignKeyInformation> getForeignKeyInformations();
public Iterable<IndexInformation> getIndexes();
/**
* todo : create an IndexInformation...
* Obtain an iterable over all the table's defined indexes
*/
public IndexInformation getIndexInformation(Identifier indexName);
public IndexInformation getIndex(Identifier indexName);
}

View File

@ -1,418 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.internal;
import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import org.hibernate.TruthValue;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.metamodel.spi.relational.Schema;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.tool.schema.spi.ColumnInformation;
import org.hibernate.tool.schema.spi.DatabaseInformation;
import org.hibernate.tool.schema.spi.SchemaManagementException;
import org.hibernate.tool.schema.spi.SequenceInformation;
import org.hibernate.tool.schema.spi.TableInformation;
/**
* @author Steve Ebersole
*/
public class DatabaseInformationImpl implements DatabaseInformation {
private final JdbcEnvironment jdbcEnvironment;
private final DatabaseMetaData databaseMetaData;
private final Map<ObjectName,TableInformationImpl> tables = new HashMap<ObjectName, TableInformationImpl>();
private final Map<ObjectName,SequenceInformation> sequences;
public static Builder builder(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) {
try {
return new BuilderImpl( jdbcEnvironment, databaseMetaData );
}
catch (SQLException e) {
throw jdbcEnvironment.getSqlExceptionHelper().convert( e, "Error accessing java.sql.DatabaseMetaData" );
}
}
private DatabaseInformationImpl(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) throws SQLException {
this.jdbcEnvironment = jdbcEnvironment;
this.databaseMetaData = databaseMetaData;
this.sequences = loadSequenceMetadataMap();
}
public IdentifierHelper identifierHelper() {
return jdbcEnvironment.getIdentifierHelper();
}
private static final String[] TABLE_TYPES = new String[] { "TABLE", "VIEW" };
private void loadTableMetadata(ResultSet resultSet) throws SQLException {
while ( resultSet.next() ) {
final Identifier catalogIdentifier = identifierHelper().fromMetaDataCatalogName(
resultSet.getString(
"TABLE_CAT"
)
);
final Identifier schemaIdentifier = identifierHelper().fromMetaDataSchemaName(
resultSet.getString(
"TABLE_SCHEM"
)
);
final Identifier tableIdentifier = identifierHelper().fromMetaDataObjectName(
resultSet.getString(
"TABLE_NAME"
)
);
final ObjectName tableName = new ObjectName( catalogIdentifier, schemaIdentifier, tableIdentifier );
// make sure it does not already exist...
TableInformationImpl tableMetadata = tables.get( tableName );
if ( tableMetadata != null ) {
throw new IllegalStateException( "Table already found on parsing database metadata [" + tableName + "]" );
}
tableMetadata = new TableInformationImpl( this, tableName );
tables.put( toMapKey( tableName ), tableMetadata );
}
}
private Map<ObjectName,SequenceInformation> loadSequenceMetadataMap() throws SQLException {
Map<ObjectName,SequenceInformation> sequences = new HashMap<ObjectName, SequenceInformation>();
// todo : temporary impl!
final Iterable<SequenceInformation> sequenceMetadatas =
new TemporarySequenceInformationExtractor( jdbcEnvironment ).extractMetadata( databaseMetaData );
if ( sequenceMetadatas != null ) {
for ( SequenceInformation sequenceInformation :sequenceMetadatas ) {
sequences.put( toMapKey( sequenceInformation.getSequenceName() ), sequenceInformation );
}
}
return sequences;
}
@Override
public TableInformation getTableInformation(ObjectName tableName) {
return tables.get( toMapKey( tableName ) );
}
public static ObjectName toMapKey(ObjectName qualifiedName) {
Identifier catalog = qualifiedName.getCatalog();
if ( catalog != null ) {
if ( ! catalog.isQuoted() ) {
catalog = Identifier.toIdentifier( catalog.getText().toUpperCase() );
}
}
Identifier schema = qualifiedName.getSchema();
if ( schema != null ) {
if ( ! schema.isQuoted() ) {
schema = Identifier.toIdentifier( schema.getText().toUpperCase() );
}
}
Identifier name = qualifiedName.getName();
if ( name != null ) {
if ( ! name.isQuoted() ) {
name = Identifier.toIdentifier( name.getText().toUpperCase() );
}
}
return new ObjectName( catalog, schema, name );
}
@Override
public SequenceInformation getSequenceInformation(ObjectName sequenceName) {
return sequences.get( toMapKey( sequenceName ) );
}
public Map<Identifier, ColumnInformation> getColumnMetadata(TableInformation tableInformation) {
final Map<Identifier, ColumnInformation> results = new HashMap<Identifier, ColumnInformation>();
try {
ResultSet resultSet = databaseMetaData.getColumns(
identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ),
identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ),
identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ),
"%"
);
try {
while ( resultSet.next() ) {
final String columnName = resultSet.getString( "COLUMN_NAME" );
if ( columnName == null ) {
continue;
}
final Identifier columnIdentifier = Identifier.toIdentifier( columnName );
if ( results.containsKey( columnIdentifier ) ) {
continue;
}
final ColumnInformationImpl meta = new ColumnInformationImpl(
tableInformation,
columnIdentifier,
resultSet.getInt( "DATA_TYPE" ),
new StringTokenizer( resultSet.getString( "TYPE_NAME" ), "() " ).nextToken(),
resultSet.getInt( "COLUMN_SIZE" ),
resultSet.getInt("DECIMAL_DIGITS"),
interpretTruthValue( resultSet.getString( "IS_NULLABLE" ) )
);
results.put( columnIdentifier, meta );
}
}
finally {
resultSet.close();
}
}
catch (SQLException e) {
throw jdbcEnvironment.getSqlExceptionHelper().convert(
e,
"Error accessing column metadata: " + tableInformation.getName().toString()
);
}
return results;
}
public Map<Identifier, IndexInformationImpl> getIndexInformation(TableInformationImpl tableInformation) {
final Map<Identifier, IndexInformationImpl.Builder> builders = new HashMap<Identifier, IndexInformationImpl.Builder>();
try {
ResultSet resultSet = databaseMetaData.getIndexInfo(
identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalog() ),
identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchema() ),
identifierHelper().toMetaDataObjectName( tableInformation.getName().getName() ),
false, // don't limit to just unique
true // do require up-to-date results
);
try {
while ( resultSet.next() ) {
if ( resultSet.getShort("TYPE") == DatabaseMetaData.tableIndexStatistic ) {
continue;
}
final Identifier indexIdentifier = Identifier.toIdentifier( resultSet.getString( "INDEX_NAME" ) );
IndexInformationImpl.Builder builder = builders.get( indexIdentifier );
if ( builder == null ) {
builder = IndexInformationImpl.builder( indexIdentifier );
builders.put( indexIdentifier, builder );
}
final Identifier columnIdentifier = Identifier.toIdentifier( resultSet.getString( "COLUMN_NAME" ) );
final ColumnInformation columnInformation = tableInformation.getColumnInformation( columnIdentifier );
if ( columnInformation == null ) {
throw new SchemaManagementException(
"Could not locate column information using identifier [" + columnIdentifier.getText() + "]"
);
}
builder.addColumn( columnInformation );
}
}
finally {
resultSet.close();
}
}
catch (SQLException e) {
throw jdbcEnvironment.getSqlExceptionHelper().convert(
e,
"Error accessing index information: " + tableInformation.getName().toString()
);
}
final Map<Identifier, IndexInformationImpl> indexes = new HashMap<Identifier, IndexInformationImpl>();
for ( IndexInformationImpl.Builder builder : builders.values() ) {
IndexInformationImpl index = builder.build();
indexes.put( index.getIndexIdentifier(), index );
}
return indexes;
}
public Map<Identifier, ForeignKeyInformationImpl> getForeignKeyMetadata(TableInformationImpl tableMetadata) {
final Map<Identifier, ForeignKeyInformationImpl.Builder> fkBuilders
= new HashMap<Identifier, ForeignKeyInformationImpl.Builder>();
try {
ResultSet resultSet = databaseMetaData.getImportedKeys(
identifierHelper().toMetaDataCatalogName( tableMetadata.getName().getCatalog() ),
identifierHelper().toMetaDataSchemaName( tableMetadata.getName().getSchema() ),
identifierHelper().toMetaDataObjectName( tableMetadata.getName().getName() )
);
// todo : need to account for getCrossReference() as well...
try {
while ( resultSet.next() ) {
// IMPL NOTE : intentionally build the builder early!
final Identifier fkIdentifier = Identifier.toIdentifier( resultSet.getString( "FK_NAME" ) );
ForeignKeyInformationImpl.Builder fkBuilder = fkBuilders.get( fkIdentifier );
if ( fkBuilder == null ) {
fkBuilder = ForeignKeyInformationImpl.builder( fkIdentifier );
fkBuilders.put( fkIdentifier, fkBuilder );
}
final ObjectName incomingPkTableName = extractKeyTableName( resultSet, "PK" );
final TableInformationImpl pkTableMetadata = tables.get( incomingPkTableName );
if ( pkTableMetadata == null ) {
// the assumption here is that we have not seen this table already based on fully-qualified name
// during previous step of building all table metadata so most likely this is
// not a match based solely on schema/catalog and that another row in this result set
// should match.
continue;
}
final Identifier fkColumnIdentifier = Identifier.toIdentifier( resultSet.getString( "FKCOLUMN_NAME" ) );
final Identifier pkColumnIdentifier = Identifier.toIdentifier( resultSet.getString( "PKCOLUMN_NAME" ) );
fkBuilder.addColumnMapping(
tableMetadata.getColumnInformation( fkColumnIdentifier ),
pkTableMetadata.getColumnInformation( pkColumnIdentifier )
);
}
}
finally {
resultSet.close();
}
}
catch (SQLException e) {
throw jdbcEnvironment.getSqlExceptionHelper().convert(
e,
"Error accessing column metadata: " + tableMetadata.getName().toString()
);
}
final Map<Identifier, ForeignKeyInformationImpl> fks = new HashMap<Identifier, ForeignKeyInformationImpl>();
for ( ForeignKeyInformationImpl.Builder fkBuilder : fkBuilders.values() ) {
ForeignKeyInformationImpl fk = fkBuilder.build();
fks.put( fk.getForeignKeyIdentifier(), fk );
}
return fks;
}
private ObjectName extractKeyTableName(ResultSet resultSet, String prefix) throws SQLException {
final String incomingCatalogName = resultSet.getString( prefix + "TABLE_SCHEM" );
final String incomingSchemaName = resultSet.getString( prefix + "TABLE_CATALOG" );
final String incomingTableName = resultSet.getString( prefix + "TABLE_NAME" );
return new ObjectName(
Identifier.toIdentifier( incomingCatalogName ), Identifier.toIdentifier( incomingSchemaName ),
Identifier.toIdentifier( incomingTableName )
);
}
private TruthValue interpretTruthValue(String nullable) {
if ( "yes".equalsIgnoreCase( nullable ) ) {
return TruthValue.TRUE;
}
else if ( "no".equalsIgnoreCase( nullable ) ) {
return TruthValue.FALSE;
}
return TruthValue.UNKNOWN;
}
public static interface Builder {
public Builder prepareAll();
public Builder prepareCatalogAndSchema(Schema.Name schemaName);
public Builder prepareCatalog(Identifier catalog);
public Builder prepareSchema(Identifier schema);
public DatabaseInformation build();
}
private static class BuilderImpl implements Builder {
private final DatabaseInformationImpl it;
public BuilderImpl(JdbcEnvironment jdbcEnvironment, DatabaseMetaData databaseMetaData) throws SQLException {
it = new DatabaseInformationImpl( jdbcEnvironment, databaseMetaData );
}
@Override
public Builder prepareAll() {
prepare( null, null );
return this;
}
private void prepare(String catalog, String schema) {
try {
ResultSet resultSet = it.databaseMetaData.getTables(
catalog,
schema,
null,
TABLE_TYPES
);
try {
it.loadTableMetadata( resultSet );
}
finally {
try {
resultSet.close();
}
catch (SQLException ignore) {
}
}
}
catch (SQLException sqlException) {
throw it.jdbcEnvironment.getSqlExceptionHelper().convert( sqlException, "Error accessing table metadata" );
}
}
@Override
public Builder prepareCatalogAndSchema(Schema.Name schemaName) {
prepare(
it.identifierHelper().toMetaDataCatalogName( schemaName.getCatalog() ),
it.identifierHelper().toMetaDataSchemaName( schemaName.getSchema() )
);
return this;
}
@Override
public Builder prepareCatalog(Identifier catalog) {
prepare(
it.identifierHelper().toMetaDataCatalogName( catalog ),
null
);
return this;
}
@Override
public Builder prepareSchema(Identifier schema) {
prepare(
null,
it.identifierHelper().toMetaDataSchemaName( schema )
);
return this;
}
@Override
public DatabaseInformation build() {
return it;
}
}
}

View File

@ -36,12 +36,12 @@ import org.hibernate.metamodel.spi.relational.Schema;
import org.hibernate.metamodel.spi.relational.Sequence;
import org.hibernate.metamodel.spi.relational.Table;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.tool.schema.spi.DatabaseInformation;
import org.hibernate.tool.schema.spi.ForeignKeyInformation;
import org.hibernate.tool.schema.extract.spi.DatabaseInformation;
import org.hibernate.tool.schema.extract.spi.ForeignKeyInformation;
import org.hibernate.tool.schema.spi.SchemaManagementException;
import org.hibernate.tool.schema.spi.SchemaMigrator;
import org.hibernate.tool.schema.spi.SequenceInformation;
import org.hibernate.tool.schema.spi.TableInformation;
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
import org.hibernate.tool.schema.extract.spi.TableInformation;
import org.hibernate.tool.schema.spi.Target;

View File

@ -29,12 +29,12 @@ import org.hibernate.metamodel.spi.relational.Schema;
import org.hibernate.metamodel.spi.relational.Sequence;
import org.hibernate.metamodel.spi.relational.Table;
import org.hibernate.metamodel.spi.relational.Value;
import org.hibernate.tool.schema.spi.ColumnInformation;
import org.hibernate.tool.schema.spi.DatabaseInformation;
import org.hibernate.tool.schema.extract.spi.ColumnInformation;
import org.hibernate.tool.schema.extract.spi.DatabaseInformation;
import org.hibernate.tool.schema.spi.SchemaManagementException;
import org.hibernate.tool.schema.spi.SchemaValidator;
import org.hibernate.tool.schema.spi.SequenceInformation;
import org.hibernate.tool.schema.spi.TableInformation;
import org.hibernate.tool.schema.extract.spi.SequenceInformation;
import org.hibernate.tool.schema.extract.spi.TableInformation;
/**
* @author Steve Ebersole
@ -74,7 +74,7 @@ public class SchemaValidatorImpl implements SchemaValidator {
for ( Value value : table.values() ) {
if ( Column.class.isInstance( value ) ) {
final Column column = (Column) value;
final ColumnInformation columnInformation = tableInformation.getColumnInformation( column.getColumnName() );
final ColumnInformation columnInformation = tableInformation.getColumn( column.getColumnName() );
if ( columnInformation == null ) {
throw new SchemaManagementException(
String.format(

View File

@ -1,100 +0,0 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
* indicated by the @author tags or express copyright attribution
* statements applied by the authors. All third-party contributions are
* distributed under license by Red Hat Inc.
*
* This copyrighted material is made available to anyone wishing to use, modify,
* copy, or redistribute it subject to the terms and conditions of the GNU
* Lesser General Public License, as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License
* for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this distribution; if not, write to:
* Free Software Foundation, Inc.
* 51 Franklin Street, Fifth Floor
* Boston, MA 02110-1301 USA
*/
package org.hibernate.tool.schema.internal;
import java.util.Map;
import org.hibernate.metamodel.spi.relational.Identifier;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.tool.schema.spi.ColumnInformation;
import org.hibernate.tool.schema.spi.ForeignKeyInformation;
import org.hibernate.tool.schema.spi.IndexInformation;
import org.hibernate.tool.schema.spi.TableInformation;
/**
* Provides access to information about existing schema objects (tables, sequences etc) of existing database.
*
* @author Christoph Sturm
* @author Max Rydahl Andersen
* @author Steve Ebersole
*/
public class TableInformationImpl implements TableInformation {
private final DatabaseInformationImpl database;
private final ObjectName tableName;
private final Map<Identifier, ColumnInformation> columns;
private Map<Identifier, ForeignKeyInformationImpl> foreignKeys;
private Map<Identifier, IndexInformationImpl> indexes;
public TableInformationImpl(DatabaseInformationImpl database, ObjectName tableName) {
this.database = database;
this.tableName = tableName;
this.columns = database.getColumnMetadata( this );
}
@Override
public ObjectName getName() {
return tableName;
}
@Override
public ColumnInformation getColumnInformation(Identifier columnIdentifier) {
return columns.get( columnIdentifier );
}
protected Map<Identifier, ForeignKeyInformationImpl> foreignKeys() {
if ( foreignKeys == null ) {
foreignKeys = database.getForeignKeyMetadata( this );
}
return foreignKeys;
}
@Override
public ForeignKeyInformation getForeignKeyInformation(Identifier fkIdentifier) {
return foreignKeys().get( fkIdentifier );
}
@Override
@SuppressWarnings("unchecked")
public Iterable getForeignKeyInformations() {
return foreignKeys().values();
}
@Override
public String toString() {
return "TableInformationImpl(" + tableName.toString() + ')';
}
protected Map<Identifier, IndexInformationImpl> indexes() {
if ( indexes == null ) {
indexes = database.getIndexInformation( this );
}
return indexes;
}
@Override
public IndexInformation getIndexInformation(Identifier indexName) {
return indexes().get( indexName );
}
}

View File

@ -26,6 +26,7 @@ package org.hibernate.tool.schema.spi;
import java.util.List;
import org.hibernate.metamodel.spi.relational.Database;
import org.hibernate.tool.schema.extract.spi.DatabaseInformation;
/**
* Service delegate for handling schema migration.

View File

@ -24,6 +24,7 @@
package org.hibernate.tool.schema.spi;
import org.hibernate.metamodel.spi.relational.Database;
import org.hibernate.tool.schema.extract.spi.DatabaseInformation;
/**
* Service delegate for handling schema validations

View File

@ -28,19 +28,20 @@ import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Properties;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.tool.schema.extract.spi.DatabaseInformation;
import org.hibernate.tool.schema.extract.spi.DatabaseInformationBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.hibernate.cfg.Environment;
import org.hibernate.dialect.Dialect;
import org.hibernate.metamodel.spi.relational.ObjectName;
import org.hibernate.service.ServiceRegistryBuilder;
import org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentImpl;
import org.hibernate.engine.jdbc.env.spi.JdbcEnvironment;
import org.hibernate.tool.schema.internal.DatabaseInformationImpl;
import org.hibernate.tool.schema.spi.DatabaseInformation;
import org.hibernate.service.spi.ServiceRegistryImplementor;
import org.hibernate.testing.junit4.BaseUnitTestCase;
import static org.junit.Assert.assertNotNull;
@ -56,7 +57,7 @@ public class ExistingDatabaseMetaDataImplTest extends BaseUnitTestCase {
@Before
public void prepare() throws SQLException {
Properties props = Environment.getProperties();
serviceRegistry = (ServiceRegistryImplementor) new ServiceRegistryBuilder().applySettings( props ).build();
serviceRegistry = (ServiceRegistryImplementor) new StandardServiceRegistryBuilder().applySettings( props ).build();
connection = DriverManager.getConnection(
props.getProperty( Environment.URL ),
props.getProperty( Environment.USER ),
@ -83,14 +84,15 @@ public class ExistingDatabaseMetaDataImplTest extends BaseUnitTestCase {
}
}
if ( serviceRegistry != null ) {
ServiceRegistryBuilder.destroy( serviceRegistry );
StandardServiceRegistryBuilder.destroy( serviceRegistry );
}
}
@Test
public void testGetTableMetadata() throws Exception {
DatabaseInformation databaseMetaData =
DatabaseInformationImpl.builder( jdbcEnvironment, connection.getMetaData() ).prepareAll().build();
DatabaseInformation databaseMetaData = new DatabaseInformationBuilder( jdbcEnvironment, connection )
.prepareAll()
.build();
ObjectName name = new ObjectName( null, null, "t1" );
assertNotNull( databaseMetaData.getTableInformation( name ) );