diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/AbstractInformationExtractorImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/AbstractInformationExtractorImpl.java index 89c53310aa..5fd9a9b8dd 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/AbstractInformationExtractorImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/AbstractInformationExtractorImpl.java @@ -6,7 +6,6 @@ package org.hibernate.tool.schema.extract.internal; import java.sql.DatabaseMetaData; import java.sql.ResultSet; -import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.util.ArrayList; import java.util.HashMap; @@ -42,6 +41,7 @@ import org.hibernate.tool.schema.spi.SchemaManagementException; import static java.util.Collections.addAll; import static org.hibernate.boot.model.naming.DatabaseIdentifier.toIdentifier; +import static org.hibernate.internal.util.StringHelper.EMPTY_STRINGS; import static org.hibernate.internal.util.StringHelper.isBlank; import static org.hibernate.internal.util.StringHelper.splitTrimmingTokens; import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean; @@ -85,31 +85,37 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt "" ) ); + final Dialect dialect = extractionContext.getJdbcEnvironment().getDialect(); + this.extraPhysicalTableTypes = getPhysicalTableTypes( extraPhysicalTableTypesConfig, dialect ); + this.tableTypes = getTableTypes( configService, dialect ); + } + + private String[] getPhysicalTableTypes(String extraPhysicalTableTypesConfig, Dialect dialect) { final List physicalTableTypesList = new ArrayList<>(); if ( !isBlank( extraPhysicalTableTypesConfig ) ) { addAll( physicalTableTypesList, splitTrimmingTokens( ",;", extraPhysicalTableTypesConfig, false ) ); } - final Dialect dialect = extractionContext.getJdbcEnvironment().getDialect(); dialect.augmentPhysicalTableTypes( physicalTableTypesList ); - this.extraPhysicalTableTypes = physicalTableTypesList.toArray( new String[0] ); + return physicalTableTypesList.toArray( EMPTY_STRINGS ); + } + private String[] getTableTypes(ConfigurationService configService, Dialect dialect) { final List tableTypesList = new ArrayList<>(); tableTypesList.add( "TABLE" ); tableTypesList.add( "VIEW" ); if ( getBoolean( AvailableSettings.ENABLE_SYNONYMS, configService.getSettings() ) ) { - if ( dialect instanceof DB2Dialect ) { + if ( dialect instanceof DB2Dialect ) { //TODO: should not use Dialect types directly! tableTypesList.add( "ALIAS" ); } tableTypesList.add( "SYNONYM" ); } addAll( tableTypesList, extraPhysicalTableTypes ); dialect.augmentRecognizedTableTypes( tableTypesList ); - - this.tableTypes = tableTypesList.toArray( new String[0] ); + return tableTypesList.toArray( EMPTY_STRINGS ); } - protected IdentifierHelper identifierHelper() { - return getIdentifierHelper(); + private IdentifierHelper getIdentifierHelper() { + return getJdbcEnvironment().getIdentifierHelper(); } protected JDBCException convertSQLException(SQLException sqlException, String message) { @@ -272,13 +278,17 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt protected abstract T processSchemaResultSet( String catalog, String schemaPattern, - ExtractionContext.ResultSetProcessor processor) throws SQLException; + ExtractionContext.ResultSetProcessor processor) + throws SQLException; @Override public boolean schemaExists(Identifier catalog, Identifier schema) { - final String catalogFilter = determineCatalogFilter( catalog ); - final String schemaFilter = determineSchemaFilter( schema ); - + final String catalogFilter = + getIdentifierHelper() + .toMetaDataCatalogName( catalog == null ? extractionContext.getDefaultCatalog() : catalog ); + final String schemaFilter = + getIdentifierHelper() + .toMetaDataSchemaName( schema == null ? extractionContext.getDefaultSchema() : schema ); try { return processSchemaResultSet( catalogFilter, @@ -308,32 +318,10 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt } } - private IdentifierHelper getIdentifierHelper() { - return getJdbcEnvironment().getIdentifierHelper(); - } - - protected String determineCatalogFilter(Identifier catalog) { - Identifier identifierToUse = catalog; - if ( identifierToUse == null ) { - identifierToUse = extractionContext.getDefaultCatalog(); - } - - return getIdentifierHelper().toMetaDataCatalogName( identifierToUse ); - } - - protected String determineSchemaFilter(Identifier schema) { - Identifier identifierToUse = schema; - if ( identifierToUse == null ) { - identifierToUse = extractionContext.getDefaultSchema(); - } - - return getIdentifierHelper().toMetaDataSchemaName( identifierToUse ); - } - private TableInformation extractTableInformation(ResultSet resultSet) throws SQLException { return new TableInformationImpl( this, - identifierHelper(), + getIdentifierHelper(), extractTableName( resultSet ), isPhysicalTableType( resultSet.getString( getResultSetTableTypeLabel() ) ), resultSet.getString( getResultSetRemarksLabel() ) @@ -616,7 +604,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt String schemaPattern, String tableNamePattern, String columnNamePattern, - ExtractionContext.ResultSetProcessor processor) throws SQLException; + ExtractionContext.ResultSetProcessor processor) + throws SQLException; private void populateTablesWithColumns( String catalogFilter, @@ -637,7 +626,7 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt currentTable = tables.getTableInformation( currentTableName ); } if ( currentTable != null ) { - addExtractedColumnInformation( currentTable, resultSet ); + currentTable.addColumn( columnInformation( currentTable, resultSet ) ); } } return null; @@ -649,9 +638,9 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt } } - protected void addExtractedColumnInformation(TableInformation tableInformation, ResultSet resultSet) + private ColumnInformationImpl columnInformation(TableInformation tableInformation, ResultSet resultSet) throws SQLException { - final ColumnInformation columnInformation = new ColumnInformationImpl( + return new ColumnInformationImpl( tableInformation, toIdentifier( resultSet.getString( getResultSetColumnNameLabel() ) ), resultSet.getInt( getResultSetSqlTypeCodeLabel() ), @@ -660,14 +649,13 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt resultSet.getInt( getResultSetDecimalDigitsLabel() ), interpretTruthValue( resultSet.getString( getResultSetIsNullableLabel() ) ) ); - tableInformation.addColumn( columnInformation ); } - private NameSpaceTablesInformation extractNameSpaceTablesInformation(ResultSet resultSet) throws SQLException { - final NameSpaceTablesInformation tables = new NameSpaceTablesInformation( identifierHelper() ); + private NameSpaceTablesInformation extractNameSpaceTablesInformation(ResultSet resultSet) + throws SQLException { + final NameSpaceTablesInformation tables = new NameSpaceTablesInformation( getIdentifierHelper() ); while ( resultSet.next() ) { - final TableInformation tableInformation = extractTableInformation( resultSet ); - tables.addTableInformation( tableInformation ); + tables.addTableInformation( extractTableInformation( resultSet ) ); } return tables; } @@ -721,8 +709,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt String schemaPattern, String tableNamePattern, String[] types, - ExtractionContext.ResultSetProcessor processor - ) throws SQLException; + ExtractionContext.ResultSetProcessor processor) + throws SQLException; private TableInformation locateTableInNamespace( Identifier catalog, @@ -735,6 +723,7 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt final String schemaFilter; final NameQualifierSupport nameQualifierSupport = getNameQualifierSupport(); + if ( nameQualifierSupport.supportsCatalogs() ) { if ( catalog == null ) { String defaultCatalog; @@ -780,12 +769,7 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt schemaFilter, tableNameFilter, tableTypes, - resultSet -> extractTableInformation( - catalogToUse, - schemaToUse, - tableName, - resultSet - ) + resultSet -> extractTableInformation( catalogToUse, schemaToUse, tableName, resultSet ) ); } @@ -802,15 +786,16 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt Identifier catalog, Identifier schema, Identifier tableName, - ResultSet resultSet) throws SQLException { + ResultSet resultSet) + throws SQLException { boolean found = false; TableInformation tableInformation = null; while ( resultSet.next() ) { - if ( tableName.equals( Identifier.toIdentifier( - resultSet.getString( getResultSetTableNameLabel() ), - tableName.isQuoted() - ) ) ) { + final Identifier identifier = + toIdentifier( resultSet.getString( getResultSetTableNameLabel() ), + tableName.isQuoted() ); + if ( tableName.equals( identifier ) ) { if ( found ) { LOG.multipleTablesFound( tableName.render() ); throw new SchemaExtractionException( @@ -867,7 +852,7 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt "%", resultSet -> { while ( resultSet.next() ) { - addExtractedColumnInformation( tableInformation, resultSet ); + tableInformation.addColumn( columnInformation( tableInformation, resultSet ) ); } return null; } @@ -879,14 +864,6 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt } } - protected Boolean interpretNullable(int nullable) { - return switch ( nullable ) { - case ResultSetMetaData.columnNullable -> Boolean.TRUE; - case ResultSetMetaData.columnNoNulls -> Boolean.FALSE; - default -> null; - }; - } - private Boolean interpretTruthValue(String nullable) { if ( "yes".equalsIgnoreCase( nullable ) ) { return Boolean.TRUE; @@ -904,7 +881,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt String catalogFilter, String schemaFilter, Identifier tableName, - ExtractionContext.ResultSetProcessor processor) throws SQLException; + ExtractionContext.ResultSetProcessor processor) + throws SQLException; @Override public PrimaryKeyInformation getPrimaryKey(TableInformationImpl tableInformation) { @@ -926,10 +904,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt } } - private PrimaryKeyInformation extractPrimaryKeyInformation( - TableInformation tableInformation, - ResultSet resultSet - ) throws SQLException { + private PrimaryKeyInformation extractPrimaryKeyInformation(TableInformation tableInformation, ResultSet resultSet) + throws SQLException { final List pkColumns = new ArrayList<>(); boolean firstPass = true; @@ -937,19 +913,16 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt while ( resultSet.next() ) { final String currentPkName = resultSet.getString( getResultSetPrimaryKeyNameLabel() ); - final Identifier currentPkIdentifier = currentPkName == null ? null : toIdentifier( currentPkName ); + final Identifier currentPkIdentifier = + currentPkName == null ? null : 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() - ) - ); + throw new SchemaExtractionException( "Encountered primary keys differing name on table " + + tableInformation.getName().toString() ); } } @@ -1054,7 +1027,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt String table, boolean unique, boolean approximate, - ExtractionContext.ResultSetProcessor processor) throws SQLException; + ExtractionContext.ResultSetProcessor processor) + throws SQLException; @Override public Iterable getIndexes(TableInformation tableInformation) { @@ -1186,8 +1160,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt String catalog, String schema, String table, - ExtractionContext.ResultSetProcessor processor - ) throws SQLException; + ExtractionContext.ResultSetProcessor processor) + throws SQLException; /** * Must do the following: @@ -1271,8 +1245,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt String foreignCatalog, String foreignSchema, String foreignTable, - ExtractionContext.ResultSetProcessor processor - ) throws SQLException; + ExtractionContext.ResultSetProcessor processor) + throws SQLException; @Override @@ -1322,8 +1296,11 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt return fks; } - private void process(TableInformation tableInformation, ResultSet resultSet, Map fkBuilders) - throws SQLException { + private void process( + TableInformation tableInformation, + ResultSet resultSet, + Map fkBuilders) + throws SQLException { while ( resultSet.next() ) { // IMPL NOTE : The builder is mainly used to collect the column reference mappings final Identifier fkIdentifier = toIdentifier( resultSet.getString( getResultSetForeignKeyLabel() ) ); diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/InformationExtractorJdbcDatabaseMetaDataImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/InformationExtractorJdbcDatabaseMetaDataImpl.java index 5306139a2c..02740dcaf1 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/InformationExtractorJdbcDatabaseMetaDataImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/InformationExtractorJdbcDatabaseMetaDataImpl.java @@ -39,8 +39,9 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform } @Override - public T processCatalogsResultSet(ExtractionContext.ResultSetProcessor processor) throws SQLException { - try (ResultSet resultSet = getJdbcDatabaseMetaData().getCatalogs() ) { + public T processCatalogsResultSet(ExtractionContext.ResultSetProcessor processor) + throws SQLException { + try ( ResultSet resultSet = getJdbcDatabaseMetaData().getCatalogs() ) { return processor.process( resultSet ); } } @@ -49,10 +50,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform protected T processSchemaResultSet( String catalog, String schemaPattern, - ExtractionContext.ResultSetProcessor processor) throws SQLException { - try (ResultSet resultSet = getJdbcDatabaseMetaData().getSchemas( - catalog, - schemaPattern ) ) { + ExtractionContext.ResultSetProcessor processor) + throws SQLException { + try ( ResultSet resultSet = + getJdbcDatabaseMetaData() + .getSchemas( catalog, schemaPattern ) ) { return processor.process( resultSet ); } } @@ -63,13 +65,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform String schemaPattern, String tableNamePattern, String[] types, - ExtractionContext.ResultSetProcessor processor - ) throws SQLException { - try (ResultSet resultSet = getJdbcDatabaseMetaData().getTables( - catalog, - schemaPattern, - tableNamePattern, - types)) { + ExtractionContext.ResultSetProcessor processor) + throws SQLException { + try ( ResultSet resultSet = + getJdbcDatabaseMetaData() + .getTables( catalog, schemaPattern, tableNamePattern, types) ) { return processor.process( resultSet ); } } @@ -80,12 +80,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform String schemaPattern, String tableNamePattern, String columnNamePattern, - ExtractionContext.ResultSetProcessor processor) throws SQLException { - try (ResultSet resultSet = getJdbcDatabaseMetaData().getColumns( - catalog, - schemaPattern, - tableNamePattern, - columnNamePattern )) { + ExtractionContext.ResultSetProcessor processor) + throws SQLException { + try ( ResultSet resultSet = + getJdbcDatabaseMetaData() + .getColumns( catalog, schemaPattern, tableNamePattern, columnNamePattern ) ) { return processor.process( resultSet ); } } @@ -95,11 +94,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform String catalogFilter, String schemaFilter, Identifier tableName, - ExtractionContext.ResultSetProcessor processor) throws SQLException { - try( ResultSet resultSet = getJdbcDatabaseMetaData().getPrimaryKeys( - catalogFilter, - schemaFilter, - tableName.getText() ) ) { + ExtractionContext.ResultSetProcessor processor) + throws SQLException { + try ( ResultSet resultSet = + getJdbcDatabaseMetaData() + .getPrimaryKeys( catalogFilter, schemaFilter, tableName.getText() ) ) { return processor.process( resultSet ); } } @@ -111,14 +110,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform String table, boolean unique, boolean approximate, - ExtractionContext.ResultSetProcessor processor) throws SQLException { - - try (ResultSet resultSet = getJdbcDatabaseMetaData().getIndexInfo( - catalog, - schema, - table, - unique, - approximate ) ) { + ExtractionContext.ResultSetProcessor processor) + throws SQLException { + try ( ResultSet resultSet = + getJdbcDatabaseMetaData() + .getIndexInfo( catalog, schema, table, unique, approximate ) ) { return processor.process( resultSet ); } } @@ -128,11 +124,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform String catalog, String schema, String table, - ExtractionContext.ResultSetProcessor processor) throws SQLException { - try (ResultSet resultSet = getJdbcDatabaseMetaData().getImportedKeys( - catalog, - schema, - table ) ) { + ExtractionContext.ResultSetProcessor processor) + throws SQLException { + try ( ResultSet resultSet = + getJdbcDatabaseMetaData() + .getImportedKeys( catalog, schema, table ) ) { return processor.process( resultSet ); } } @@ -145,14 +141,12 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform String foreignCatalog, String foreignSchema, String foreignTable, - ExtractionContext.ResultSetProcessor processor) throws SQLException { - try (ResultSet resultSet = getJdbcDatabaseMetaData().getCrossReference( - parentCatalog, - parentSchema, - parentTable, - foreignCatalog, - foreignSchema, - foreignTable) ) { + ExtractionContext.ResultSetProcessor processor) + throws SQLException { + try ( ResultSet resultSet = + getJdbcDatabaseMetaData() + .getCrossReference( parentCatalog, parentSchema, parentTable, + foreignCatalog, foreignSchema, foreignTable) ) { return processor.process( resultSet ); } } @@ -162,12 +156,12 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform final ExtractionContext extractionContext = getExtractionContext(); // We use this dummy query to retrieve the table information through the ResultSetMetaData - // This is significantly better than to use the DatabaseMetaData especially on Oracle with synonyms enabled - final String tableName = extractionContext.getSqlStringGenerationContext().format( - // The name comes from the database, so the case is correct - // But we quote here to avoid issues with reserved words - tableInformation.getName().quote() - ); + // Significantly better than using DatabaseMetaData especially on Oracle with synonyms enabled + final String tableName = + extractionContext.getSqlStringGenerationContext() + // The name comes from the database, so the case is correct + // But we quote here to avoid issues with reserved words + .format( tableInformation.getName().quote() ); try { extractionContext.getQueryResults( @@ -176,38 +170,51 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform resultSet -> { final ResultSetMetaData metaData = resultSet.getMetaData(); final int columnCount = metaData.getColumnCount(); - for ( int i = 1; i <= columnCount; i++ ) { - final String columnName = metaData.getColumnName( i ); - final int columnType = metaData.getColumnType( i ); - final String typeName = new StringTokenizer( metaData.getColumnTypeName( i ), "()" ).nextToken(); - final int scale = metaData.getScale( i ); - final ColumnInformationImpl columnInformation = new ColumnInformationImpl( - tableInformation, - DatabaseIdentifier.toIdentifier( columnName ), - columnType, - typeName, - dialect.resolveSqlTypeLength( - typeName, - columnType, - metaData.getPrecision( i ), - scale, - metaData.getColumnDisplaySize( i ) - ), - scale, - interpretNullable( metaData.isNullable( i ) ) - ); - tableInformation.addColumn( columnInformation ); + tableInformation.addColumn( columnInformation( tableInformation, metaData, i, dialect ) ); } return null; } ); } catch (SQLException e) { - throw convertSQLException( - e, - "Error accessing column metadata: " + tableInformation.getName().toString() - ); + throw convertSQLException( e, + "Error accessing column metadata: " + + tableInformation.getName().toString() ); } } + + private static Boolean interpretNullable(int nullable) { + return switch ( nullable ) { + case ResultSetMetaData.columnNullable -> Boolean.TRUE; + case ResultSetMetaData.columnNoNulls -> Boolean.FALSE; + default -> null; + }; + } + + private static ColumnInformationImpl columnInformation( + TableInformation tableInformation, ResultSetMetaData metaData, int i, Dialect dialect) + throws SQLException { + final String columnName = metaData.getColumnName( i ); + final int columnType = metaData.getColumnType( i ); + final String typeName = + new StringTokenizer( metaData.getColumnTypeName( i ), "()" ) + .nextToken(); + final int scale = metaData.getScale( i ); + return new ColumnInformationImpl( + tableInformation, + DatabaseIdentifier.toIdentifier( columnName ), + columnType, + typeName, + dialect.resolveSqlTypeLength( + typeName, + columnType, + metaData.getPrecision( i ), + scale, + metaData.getColumnDisplaySize( i ) + ), + scale, + interpretNullable( metaData.isNullable( i ) ) + ); + } } diff --git a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java index 4ca77c3c28..8be137646f 100644 --- a/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java +++ b/hibernate-core/src/main/java/org/hibernate/tool/schema/extract/internal/TableInformationImpl.java @@ -35,7 +35,7 @@ public class TableInformationImpl implements TableInformation { private PrimaryKeyInformation primaryKey; private Map foreignKeys; private Map indexes; - private Map columns = new HashMap<>( ); + private final Map columns = new HashMap<>(); private boolean wasPrimaryKeyLoaded = false; // to avoid multiple db reads since primary key can be null.