org.hibernate.tool.schema.extract.internal.InformationExtractorJdbcDatabaseMetaDataImpl Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of hibernate-core Show documentation
Show all versions of hibernate-core Show documentation
JPMS Module-Info's for a few of the Jakarta Libraries just until they add them in themselves
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
* See the lgpl.txt file in the root directory or .
*/
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.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.StringTokenizer;
import org.hibernate.JDBCException;
import org.hibernate.boot.model.TruthValue;
import org.hibernate.boot.model.naming.DatabaseIdentifier;
import org.hibernate.boot.model.naming.Identifier;
import org.hibernate.boot.model.relational.QualifiedTableName;
import org.hibernate.cfg.AvailableSettings;
import org.hibernate.engine.config.spi.ConfigurationService;
import org.hibernate.engine.config.spi.StandardConverters;
import org.hibernate.engine.jdbc.env.spi.IdentifierHelper;
import org.hibernate.internal.CoreLogging;
import org.hibernate.internal.CoreMessageLogger;
import org.hibernate.internal.util.StringHelper;
import org.hibernate.internal.util.config.ConfigurationHelper;
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.InformationExtractor;
import org.hibernate.tool.schema.extract.spi.NameSpaceTablesInformation;
import org.hibernate.tool.schema.extract.spi.PrimaryKeyInformation;
import org.hibernate.tool.schema.extract.spi.SchemaExtractionException;
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 InformationExtractorJdbcDatabaseMetaDataImpl implements InformationExtractor {
private static final CoreMessageLogger log = CoreLogging.messageLogger( InformationExtractorJdbcDatabaseMetaDataImpl.class );
private final String[] tableTypes;
private String[] extraPhysicalTableTypes;
private final ExtractionContext extractionContext;
public InformationExtractorJdbcDatabaseMetaDataImpl(ExtractionContext extractionContext) {
this.extractionContext = extractionContext;
ConfigurationService configService = extractionContext.getServiceRegistry()
.getService( ConfigurationService.class );
final String extraPhysycalTableTypesConfig = configService.getSetting(
AvailableSettings.EXTRA_PHYSICAL_TABLE_TYPES,
StandardConverters.STRING,
configService.getSetting(
AvailableSettings.DEPRECATED_EXTRA_PHYSICAL_TABLE_TYPES,
StandardConverters.STRING,
""
)
);
if ( !"".equals( extraPhysycalTableTypesConfig.trim() ) ) {
this.extraPhysicalTableTypes = StringHelper.splitTrimmingTokens(
",;",
extraPhysycalTableTypesConfig,
false
);
}
final List tableTypesList = new ArrayList<>();
tableTypesList.add( "TABLE" );
tableTypesList.add( "VIEW" );
if ( ConfigurationHelper.getBoolean( AvailableSettings.ENABLE_SYNONYMS, configService.getSettings(), false ) ) {
tableTypesList.add( "SYNONYM" );
}
if ( extraPhysicalTableTypes != null ) {
Collections.addAll( tableTypesList, extraPhysicalTableTypes );
}
extractionContext.getJdbcEnvironment().getDialect().augmentRecognizedTableTypes( tableTypesList );
this.tableTypes = tableTypesList.toArray( new String[ tableTypesList.size() ] );
}
protected IdentifierHelper identifierHelper() {
return extractionContext.getJdbcEnvironment().getIdentifierHelper();
}
protected JDBCException convertSQLException(SQLException sqlException, String message) {
return extractionContext.getJdbcEnvironment().getSqlExceptionHelper().convert( sqlException, message );
}
protected String toMetaDataObjectName(Identifier identifier) {
return extractionContext.getJdbcEnvironment().getIdentifierHelper().toMetaDataObjectName( identifier );
}
@Override
public boolean catalogExists(Identifier catalog) {
try {
final ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getCatalogs();
try {
while ( resultSet.next() ) {
final String existingCatalogName = resultSet.getString( "TABLE_CAT" );
// todo : hmm.. case sensitive or insensitive match...
// for now, match any case...
if ( catalog.getText().equalsIgnoreCase( existingCatalogName ) ) {
return true;
}
}
return false;
}
finally {
try {
resultSet.close();
}
catch (SQLException ignore) {
}
}
}
catch (SQLException sqlException) {
throw convertSQLException( sqlException, "Unable to query DatabaseMetaData for existing catalogs" );
}
}
@Override
public boolean schemaExists(Identifier catalog, Identifier schema) {
try {
final String catalogFilter = determineCatalogFilter( catalog );
final String schemaFilter = determineSchemaFilter( schema );
final ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getSchemas(
catalogFilter,
schemaFilter
);
try {
if ( !resultSet.next() ) {
return false;
}
if ( resultSet.next() ) {
final String catalogName = catalog == null ? "" : catalog.getCanonicalName();
final String schemaName = schema == null ? "" : schema.getCanonicalName();
log.debugf(
"Multiple schemas found with that name [%s.%s]",
catalogName,
schemaName
);
}
return true;
}
finally {
try {
resultSet.close();
}
catch (SQLException ignore) {
}
}
}
catch (SQLException sqlException) {
throw convertSQLException( sqlException, "Unable to query DatabaseMetaData for existing schemas" );
}
}
private String determineCatalogFilter(Identifier catalog) throws SQLException {
Identifier identifierToUse = catalog;
if ( identifierToUse == null ) {
identifierToUse = extractionContext.getDefaultCatalog();
}
return extractionContext.getJdbcEnvironment().getIdentifierHelper().toMetaDataCatalogName( identifierToUse );
}
private String determineSchemaFilter(Identifier schema) throws SQLException {
Identifier identifierToUse = schema;
if ( identifierToUse == null ) {
identifierToUse = extractionContext.getDefaultSchema();
}
return extractionContext.getJdbcEnvironment().getIdentifierHelper().toMetaDataSchemaName( identifierToUse );
}
private TableInformation extractTableInformation(ResultSet resultSet) throws SQLException {
final QualifiedTableName tableName = extractTableName( resultSet );
final TableInformationImpl tableInformation = new TableInformationImpl(
this,
identifierHelper(),
tableName,
isPhysicalTableType( resultSet.getString( "TABLE_TYPE" ) ),
resultSet.getString( "REMARKS" )
);
return tableInformation;
}
@Override
public TableInformation getTable(Identifier catalog, Identifier schema, Identifier tableName) {
if ( catalog != null || schema != null ) {
// The table defined an explicit namespace. In such cases we only ever want to look
// in the identified namespace
return locateTableInNamespace( catalog, schema, tableName );
}
else {
// The table did not define an explicit namespace:
// 1) look in current namespace
// 2) look in default namespace
// 3) look in all namespaces - multiple hits is considered an error
TableInformation tableInfo = null;
// 1) look in current namespace
if ( extractionContext.getJdbcEnvironment().getCurrentCatalog() != null
|| extractionContext.getJdbcEnvironment().getCurrentSchema() != null ) {
tableInfo = locateTableInNamespace(
extractionContext.getJdbcEnvironment().getCurrentCatalog(),
extractionContext.getJdbcEnvironment().getCurrentSchema(),
tableName
);
if ( tableInfo != null ) {
return tableInfo;
}
}
// 2) look in default namespace
if ( extractionContext.getDefaultCatalog() != null || extractionContext.getDefaultSchema() != null ) {
tableInfo = locateTableInNamespace(
extractionContext.getDefaultCatalog(),
extractionContext.getDefaultSchema(),
tableName
);
if ( tableInfo != null ) {
return tableInfo;
}
}
// 3) look in all namespaces
try {
final String tableNameFilter = toMetaDataObjectName( tableName );
final ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getTables(
null,
null,
tableNameFilter,
tableTypes
);
try {
return processTableResults(
null,
null,
tableName,
resultSet
);
}
finally {
try {
resultSet.close();
}
catch (SQLException ignore) {
}
}
}
catch (SQLException sqlException) {
throw convertSQLException( sqlException, "Error accessing table metadata" );
}
}
}
public NameSpaceTablesInformation getTables(Identifier catalog, Identifier schema) {
String catalogFilter = null;
String schemaFilter = null;
if ( extractionContext.getJdbcEnvironment().getNameQualifierSupport().supportsCatalogs() ) {
if ( catalog == null ) {
if ( extractionContext.getJdbcEnvironment().getCurrentCatalog() != null ) {
// 1) look in current namespace
catalogFilter = toMetaDataObjectName( extractionContext.getJdbcEnvironment().getCurrentCatalog() );
}
else if ( extractionContext.getDefaultCatalog() != null ) {
// 2) look in default namespace
catalogFilter = toMetaDataObjectName( extractionContext.getDefaultCatalog() );
}
else {
catalogFilter = "";
}
}
else {
catalogFilter = toMetaDataObjectName( catalog );
}
}
if ( extractionContext.getJdbcEnvironment().getNameQualifierSupport().supportsSchemas() ) {
if ( schema == null ) {
if ( extractionContext.getJdbcEnvironment().getCurrentSchema() != null ) {
// 1) look in current namespace
schemaFilter = toMetaDataObjectName( extractionContext.getJdbcEnvironment().getCurrentSchema() );
}
else if ( extractionContext.getDefaultSchema() != null ) {
// 2) look in default namespace
schemaFilter = toMetaDataObjectName( extractionContext.getDefaultSchema() );
}
else {
schemaFilter = "";
}
}
else {
schemaFilter = toMetaDataObjectName( schema );
}
}
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getTables(
catalogFilter,
schemaFilter,
"%",
tableTypes
);
final NameSpaceTablesInformation tablesInformation = processTableResults( resultSet );
populateTablesWithColumns( catalogFilter, schemaFilter, tablesInformation );
return tablesInformation;
}
catch (SQLException sqlException) {
throw convertSQLException( sqlException, "Error accessing table metadata" );
}
}
private void populateTablesWithColumns(
String catalogFilter,
String schemaFilter,
NameSpaceTablesInformation tables) {
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getColumns(
catalogFilter,
schemaFilter,
null,
"%"
);
try {
String currentTableName = "";
TableInformation currentTable = null;
while ( resultSet.next() ) {
if ( !currentTableName.equals( resultSet.getString( "TABLE_NAME" ) ) ) {
currentTableName = resultSet.getString( "TABLE_NAME" );
currentTable = tables.getTableInformation( currentTableName );
}
if ( currentTable != null ) {
final ColumnInformationImpl columnInformation = new ColumnInformationImpl(
currentTable,
DatabaseIdentifier.toIdentifier( resultSet.getString( "COLUMN_NAME" ) ),
resultSet.getInt( "DATA_TYPE" ),
new StringTokenizer( resultSet.getString( "TYPE_NAME" ), "() " ).nextToken(),
resultSet.getInt( "COLUMN_SIZE" ),
resultSet.getInt( "DECIMAL_DIGITS" ),
interpretTruthValue( resultSet.getString( "IS_NULLABLE" ) )
);
currentTable.addColumn( columnInformation );
}
}
}
finally {
resultSet.close();
}
}
catch (SQLException e) {
throw convertSQLException(
e,
"Error accessing tables metadata"
);
}
}
private NameSpaceTablesInformation processTableResults(ResultSet resultSet) throws SQLException {
try {
NameSpaceTablesInformation tables = new NameSpaceTablesInformation(identifierHelper());
while ( resultSet.next() ) {
final TableInformation tableInformation = extractTableInformation( resultSet );
tables.addTableInformation( tableInformation );
}
return tables;
}
finally {
try {
resultSet.close();
}
catch (SQLException ignore) {
}
}
}
private TableInformation locateTableInNamespace(
Identifier catalog,
Identifier schema,
Identifier tableName) {
Identifier catalogToUse = null;
Identifier schemaToUse = null;
final String catalogFilter;
final String schemaFilter;
if ( extractionContext.getJdbcEnvironment().getNameQualifierSupport().supportsCatalogs() ) {
if ( catalog == null ) {
String defaultCatalog = "";
if ( extractionContext.getJdbcEnvironment().getNameQualifierSupport().supportsCatalogs() ) {
try {
defaultCatalog = extractionContext.getJdbcConnection().getCatalog();
}
catch (SQLException ignore) {
}
}
catalogFilter = defaultCatalog;
}
else {
catalogToUse = catalog;
catalogFilter = toMetaDataObjectName( catalog );
}
}
else {
catalogFilter = null;
}
if ( extractionContext.getJdbcEnvironment().getNameQualifierSupport().supportsSchemas() ) {
if ( schema == null ) {
schemaFilter = "";
}
else {
schemaToUse = schema;
schemaFilter = toMetaDataObjectName( schema );
}
}
else {
schemaFilter = null;
}
final String tableNameFilter = toMetaDataObjectName( tableName );
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getTables(
catalogFilter,
schemaFilter,
tableNameFilter,
tableTypes
);
return processTableResults(
catalogToUse,
schemaToUse,
tableName,
resultSet
);
}
catch (SQLException sqlException) {
throw convertSQLException( sqlException, "Error accessing table metadata" );
}
}
private TableInformation processTableResults(
Identifier catalog,
Identifier schema,
Identifier tableName,
ResultSet resultSet) throws SQLException {
try {
boolean found = false;
TableInformation tableInformation = null;
while ( resultSet.next() ) {
if ( tableName.equals( Identifier.toIdentifier( resultSet.getString( "TABLE_NAME" ),
tableName.isQuoted() ) ) ) {
if ( found ) {
log.multipleTablesFound( tableName.render() );
final String catalogName = catalog == null ? "" : catalog.render();
final String schemaName = schema == null ? "" : schema.render();
throw new SchemaExtractionException(
String.format(
Locale.ENGLISH,
"More than one table found in namespace (%s, %s) : %s",
catalogName,
schemaName,
tableName.render()
)
);
}
else {
found = true;
tableInformation = extractTableInformation( resultSet );
addColumns( tableInformation );
}
}
}
if ( !found ) {
log.tableNotFound( tableName.render() );
}
return tableInformation;
}
finally {
try {
resultSet.close();
}
catch (SQLException ignore) {
}
}
}
protected boolean isPhysicalTableType(String tableType) {
if ( extraPhysicalTableTypes == null ) {
return "TABLE".equalsIgnoreCase( tableType );
}
else {
if ( "TABLE".equalsIgnoreCase( tableType ) ) {
return true;
}
for ( String extraPhysicalTableType : extraPhysicalTableTypes ) {
if ( extraPhysicalTableType.equalsIgnoreCase( tableType ) ) {
return true;
}
}
return false;
}
}
private void addColumns(TableInformation tableInformation) {
final QualifiedTableName tableName = tableInformation.getName();
final Identifier catalog = tableName.getCatalogName();
final Identifier schema = tableName.getSchemaName();
final String catalogFilter;
final String schemaFilter;
if ( catalog == null ) {
catalogFilter = "";
}
else {
catalogFilter = catalog.getText();
}
if ( schema == null ) {
schemaFilter = "";
}
else {
schemaFilter = schema.getText();
}
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getColumns(
catalogFilter,
schemaFilter,
tableName.getTableName().getText(),
"%"
);
try {
while ( resultSet.next() ) {
final String columnName = resultSet.getString( "COLUMN_NAME" );
final ColumnInformationImpl columnInformation = new ColumnInformationImpl(
tableInformation,
DatabaseIdentifier.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" ) )
);
tableInformation.addColumn( columnInformation );
}
}
finally {
resultSet.close();
}
}
catch (SQLException e) {
throw convertSQLException(
e,
"Error accessing column metadata: " + tableName.toString()
);
}
}
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 PrimaryKeyInformation getPrimaryKey(TableInformationImpl tableInformation) {
final QualifiedTableName tableName = tableInformation.getName();
final Identifier catalog = tableName.getCatalogName();
final Identifier schema = tableName.getSchemaName();
final String catalogFilter;
final String schemaFilter;
if ( catalog == null ) {
catalogFilter = "";
}
else {
catalogFilter = catalog.getText();
}
if ( schema == null ) {
schemaFilter = "";
}
else {
schemaFilter = schema.getText();
}
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getPrimaryKeys(
catalogFilter,
schemaFilter,
tableInformation.getName().getTableName().getText()
);
final List pkColumns = new ArrayList();
boolean firstPass = true;
Identifier pkIdentifier = null;
try {
while ( resultSet.next() ) {
final String currentPkName = resultSet.getString( "PK_NAME" );
final Identifier currentPkIdentifier = currentPkName == null
? null
: DatabaseIdentifier.toIdentifier( currentPkName );
if ( firstPass ) {
pkIdentifier = currentPkIdentifier;
firstPass = false;
}
else {
if ( !Objects.equals( pkIdentifier, currentPkIdentifier ) ) {
throw new SchemaExtractionException(
String.format(
"Encountered primary keys differing name on table %s",
tableInformation.getName().toString()
)
);
}
}
final int columnPosition = resultSet.getInt( "KEY_SEQ" );
final Identifier columnIdentifier = DatabaseIdentifier.toIdentifier(
resultSet.getString( "COLUMN_NAME" )
);
final ColumnInformation column = tableInformation.getColumn( columnIdentifier );
pkColumns.add( columnPosition-1, column );
}
}
finally {
resultSet.close();
}
if ( firstPass ) {
// we did not find any results (no pk)
return null;
}
else {
// validate column list is properly contiguous
for ( int i = 0; i < pkColumns.size(); i++ ) {
if ( pkColumns.get( i ) == null ) {
throw new SchemaExtractionException( "Primary Key information was missing for KEY_SEQ = " + ( i+1) );
}
}
// build the return
return new PrimaryKeyInformationImpl( pkIdentifier, pkColumns );
}
}
catch (SQLException e) {
throw convertSQLException( e, "Error while reading primary key meta data for " + tableInformation.getName().toString() );
}
}
@Override
public Iterable getIndexes(TableInformation tableInformation) {
final Map builders = new HashMap<>();
final QualifiedTableName tableName = tableInformation.getName();
final Identifier catalog = tableName.getCatalogName();
final Identifier schema = tableName.getSchemaName();
final String catalogFilter;
final String schemaFilter;
if ( catalog == null ) {
catalogFilter = "";
}
else {
catalogFilter = catalog.getText();
}
if ( schema == null ) {
schemaFilter = "";
}
else {
schemaFilter = schema.getText();
}
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getIndexInfo(
catalogFilter,
schemaFilter,
tableName.getTableName().getText(),
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 = DatabaseIdentifier.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 = DatabaseIdentifier.toIdentifier( resultSet.getString( "COLUMN_NAME" ) );
final ColumnInformation columnInformation = tableInformation.getColumn( columnIdentifier );
if ( columnInformation == null ) {
// See HHH-10191: this may happen when dealing with Oracle/PostgreSQL function indexes
log.logCannotLocateIndexColumnInformation(
columnIdentifier.getText(),
indexIdentifier.getText()
);
}
builder.addColumn( columnInformation );
}
}
finally {
resultSet.close();
}
}
catch (SQLException e) {
throw convertSQLException(
e,
"Error accessing index information: " + tableInformation.getName().toString()
);
}
final List indexes = new ArrayList();
for ( IndexInformationImpl.Builder builder : builders.values() ) {
IndexInformationImpl index = builder.build();
indexes.add( index );
}
return indexes;
}
@Override
public Iterable getForeignKeys(TableInformation tableInformation) {
final Map fkBuilders = new HashMap<>();
final QualifiedTableName tableName = tableInformation.getName();
final Identifier catalog = tableName.getCatalogName();
final Identifier schema = tableName.getSchemaName();
final String catalogFilter;
final String schemaFilter;
if ( catalog == null ) {
catalogFilter = "";
}
else {
catalogFilter = catalog.getText();
}
if ( schema == null ) {
schemaFilter = "";
}
else {
schemaFilter = schema.getText();
}
try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getImportedKeys(
catalogFilter,
schemaFilter,
tableInformation.getName().getTableName().getText()
);
// 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 = DatabaseIdentifier.toIdentifier(
resultSet.getString( "FK_NAME" )
);
ForeignKeyBuilder fkBuilder = fkBuilders.get( fkIdentifier );
if ( fkBuilder == null ) {
fkBuilder = generateForeignKeyBuilder( fkIdentifier );
fkBuilders.put( fkIdentifier, fkBuilder );
}
final QualifiedTableName incomingPkTableName = extractKeyTableName( resultSet, "PK" );
final TableInformation pkTableInformation = extractionContext.getDatabaseObjectAccess()
.locateTableInformation( 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 = DatabaseIdentifier.toIdentifier(
resultSet.getString( "FKCOLUMN_NAME" )
);
final Identifier pkColumnIdentifier = DatabaseIdentifier.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 fks = new ArrayList();
for ( ForeignKeyBuilder fkBuilder : fkBuilders.values() ) {
ForeignKeyInformation fk = fkBuilder.build();
fks.add( fk );
}
return fks;
}
private ForeignKeyBuilder generateForeignKeyBuilder(Identifier fkIdentifier) {
return new ForeignKeyBuilderImpl( fkIdentifier );
}
protected interface ForeignKeyBuilder {
ForeignKeyBuilder addColumnMapping(ColumnInformation referencing, ColumnInformation referenced);
ForeignKeyInformation build();
}
protected static class ForeignKeyBuilderImpl implements ForeignKeyBuilder {
private final Identifier fkIdentifier;
private final List columnMappingList = new ArrayList();
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 QualifiedTableName extractKeyTableName(ResultSet resultSet, String prefix) throws SQLException {
final String incomingCatalogName = resultSet.getString( prefix + "TABLE_CAT" );
final String incomingSchemaName = resultSet.getString( prefix + "TABLE_SCHEM" );
final String incomingTableName = resultSet.getString( prefix + "TABLE_NAME" );
final DatabaseIdentifier catalog = DatabaseIdentifier.toIdentifier( incomingCatalogName );
final DatabaseIdentifier schema = DatabaseIdentifier.toIdentifier( incomingSchemaName );
final DatabaseIdentifier table = DatabaseIdentifier.toIdentifier( incomingTableName );
return new QualifiedTableName( catalog, schema, table );
}
private QualifiedTableName extractTableName(ResultSet resultSet) throws SQLException {
final String incomingCatalogName = resultSet.getString( "TABLE_CAT" );
final String incomingSchemaName = resultSet.getString( "TABLE_SCHEM" );
final String incomingTableName = resultSet.getString( "TABLE_NAME" );
final DatabaseIdentifier catalog = DatabaseIdentifier.toIdentifier( incomingCatalogName );
final DatabaseIdentifier schema = DatabaseIdentifier.toIdentifier( incomingSchemaName );
final DatabaseIdentifier table = DatabaseIdentifier.toIdentifier( incomingTableName );
return new QualifiedTableName( catalog, schema, table );
}
}