cleanups to InformationExtractorJdbcDatabaseMetaDataImpl

and more to AbstractInformationExtractorImpl
This commit is contained in:
Gavin King 2024-11-14 11:43:07 +01:00
parent 5d5ce3feda
commit d20de1f5d7
3 changed files with 146 additions and 162 deletions

View File

@ -6,7 +6,6 @@ package org.hibernate.tool.schema.extract.internal;
import java.sql.DatabaseMetaData; import java.sql.DatabaseMetaData;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@ -42,6 +41,7 @@ import org.hibernate.tool.schema.spi.SchemaManagementException;
import static java.util.Collections.addAll; import static java.util.Collections.addAll;
import static org.hibernate.boot.model.naming.DatabaseIdentifier.toIdentifier; 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.isBlank;
import static org.hibernate.internal.util.StringHelper.splitTrimmingTokens; import static org.hibernate.internal.util.StringHelper.splitTrimmingTokens;
import static org.hibernate.internal.util.config.ConfigurationHelper.getBoolean; 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<String> physicalTableTypesList = new ArrayList<>(); final List<String> physicalTableTypesList = new ArrayList<>();
if ( !isBlank( extraPhysicalTableTypesConfig ) ) { if ( !isBlank( extraPhysicalTableTypesConfig ) ) {
addAll( physicalTableTypesList, splitTrimmingTokens( ",;", extraPhysicalTableTypesConfig, false ) ); addAll( physicalTableTypesList, splitTrimmingTokens( ",;", extraPhysicalTableTypesConfig, false ) );
} }
final Dialect dialect = extractionContext.getJdbcEnvironment().getDialect();
dialect.augmentPhysicalTableTypes( physicalTableTypesList ); dialect.augmentPhysicalTableTypes( physicalTableTypesList );
this.extraPhysicalTableTypes = physicalTableTypesList.toArray( new String[0] ); return physicalTableTypesList.toArray( EMPTY_STRINGS );
}
private String[] getTableTypes(ConfigurationService configService, Dialect dialect) {
final List<String> tableTypesList = new ArrayList<>(); final List<String> tableTypesList = new ArrayList<>();
tableTypesList.add( "TABLE" ); tableTypesList.add( "TABLE" );
tableTypesList.add( "VIEW" ); tableTypesList.add( "VIEW" );
if ( getBoolean( AvailableSettings.ENABLE_SYNONYMS, configService.getSettings() ) ) { 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( "ALIAS" );
} }
tableTypesList.add( "SYNONYM" ); tableTypesList.add( "SYNONYM" );
} }
addAll( tableTypesList, extraPhysicalTableTypes ); addAll( tableTypesList, extraPhysicalTableTypes );
dialect.augmentRecognizedTableTypes( tableTypesList ); dialect.augmentRecognizedTableTypes( tableTypesList );
return tableTypesList.toArray( EMPTY_STRINGS );
this.tableTypes = tableTypesList.toArray( new String[0] );
} }
protected IdentifierHelper identifierHelper() { private IdentifierHelper getIdentifierHelper() {
return getIdentifierHelper(); return getJdbcEnvironment().getIdentifierHelper();
} }
protected JDBCException convertSQLException(SQLException sqlException, String message) { protected JDBCException convertSQLException(SQLException sqlException, String message) {
@ -272,13 +278,17 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
protected abstract <T> T processSchemaResultSet( protected abstract <T> T processSchemaResultSet(
String catalog, String catalog,
String schemaPattern, String schemaPattern,
ExtractionContext.ResultSetProcessor<T> processor) throws SQLException; ExtractionContext.ResultSetProcessor<T> processor)
throws SQLException;
@Override @Override
public boolean schemaExists(Identifier catalog, Identifier schema) { public boolean schemaExists(Identifier catalog, Identifier schema) {
final String catalogFilter = determineCatalogFilter( catalog ); final String catalogFilter =
final String schemaFilter = determineSchemaFilter( schema ); getIdentifierHelper()
.toMetaDataCatalogName( catalog == null ? extractionContext.getDefaultCatalog() : catalog );
final String schemaFilter =
getIdentifierHelper()
.toMetaDataSchemaName( schema == null ? extractionContext.getDefaultSchema() : schema );
try { try {
return processSchemaResultSet( return processSchemaResultSet(
catalogFilter, 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 { private TableInformation extractTableInformation(ResultSet resultSet) throws SQLException {
return new TableInformationImpl( return new TableInformationImpl(
this, this,
identifierHelper(), getIdentifierHelper(),
extractTableName( resultSet ), extractTableName( resultSet ),
isPhysicalTableType( resultSet.getString( getResultSetTableTypeLabel() ) ), isPhysicalTableType( resultSet.getString( getResultSetTableTypeLabel() ) ),
resultSet.getString( getResultSetRemarksLabel() ) resultSet.getString( getResultSetRemarksLabel() )
@ -616,7 +604,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
String schemaPattern, String schemaPattern,
String tableNamePattern, String tableNamePattern,
String columnNamePattern, String columnNamePattern,
ExtractionContext.ResultSetProcessor<T> processor) throws SQLException; ExtractionContext.ResultSetProcessor<T> processor)
throws SQLException;
private void populateTablesWithColumns( private void populateTablesWithColumns(
String catalogFilter, String catalogFilter,
@ -637,7 +626,7 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
currentTable = tables.getTableInformation( currentTableName ); currentTable = tables.getTableInformation( currentTableName );
} }
if ( currentTable != null ) { if ( currentTable != null ) {
addExtractedColumnInformation( currentTable, resultSet ); currentTable.addColumn( columnInformation( currentTable, resultSet ) );
} }
} }
return null; 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 { throws SQLException {
final ColumnInformation columnInformation = new ColumnInformationImpl( return new ColumnInformationImpl(
tableInformation, tableInformation,
toIdentifier( resultSet.getString( getResultSetColumnNameLabel() ) ), toIdentifier( resultSet.getString( getResultSetColumnNameLabel() ) ),
resultSet.getInt( getResultSetSqlTypeCodeLabel() ), resultSet.getInt( getResultSetSqlTypeCodeLabel() ),
@ -660,14 +649,13 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
resultSet.getInt( getResultSetDecimalDigitsLabel() ), resultSet.getInt( getResultSetDecimalDigitsLabel() ),
interpretTruthValue( resultSet.getString( getResultSetIsNullableLabel() ) ) interpretTruthValue( resultSet.getString( getResultSetIsNullableLabel() ) )
); );
tableInformation.addColumn( columnInformation );
} }
private NameSpaceTablesInformation extractNameSpaceTablesInformation(ResultSet resultSet) throws SQLException { private NameSpaceTablesInformation extractNameSpaceTablesInformation(ResultSet resultSet)
final NameSpaceTablesInformation tables = new NameSpaceTablesInformation( identifierHelper() ); throws SQLException {
final NameSpaceTablesInformation tables = new NameSpaceTablesInformation( getIdentifierHelper() );
while ( resultSet.next() ) { while ( resultSet.next() ) {
final TableInformation tableInformation = extractTableInformation( resultSet ); tables.addTableInformation( extractTableInformation( resultSet ) );
tables.addTableInformation( tableInformation );
} }
return tables; return tables;
} }
@ -721,8 +709,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
String schemaPattern, String schemaPattern,
String tableNamePattern, String tableNamePattern,
String[] types, String[] types,
ExtractionContext.ResultSetProcessor<T> processor ExtractionContext.ResultSetProcessor<T> processor)
) throws SQLException; throws SQLException;
private TableInformation locateTableInNamespace( private TableInformation locateTableInNamespace(
Identifier catalog, Identifier catalog,
@ -735,6 +723,7 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
final String schemaFilter; final String schemaFilter;
final NameQualifierSupport nameQualifierSupport = getNameQualifierSupport(); final NameQualifierSupport nameQualifierSupport = getNameQualifierSupport();
if ( nameQualifierSupport.supportsCatalogs() ) { if ( nameQualifierSupport.supportsCatalogs() ) {
if ( catalog == null ) { if ( catalog == null ) {
String defaultCatalog; String defaultCatalog;
@ -780,12 +769,7 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
schemaFilter, schemaFilter,
tableNameFilter, tableNameFilter,
tableTypes, tableTypes,
resultSet -> extractTableInformation( resultSet -> extractTableInformation( catalogToUse, schemaToUse, tableName, resultSet )
catalogToUse,
schemaToUse,
tableName,
resultSet
)
); );
} }
@ -802,15 +786,16 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
Identifier catalog, Identifier catalog,
Identifier schema, Identifier schema,
Identifier tableName, Identifier tableName,
ResultSet resultSet) throws SQLException { ResultSet resultSet)
throws SQLException {
boolean found = false; boolean found = false;
TableInformation tableInformation = null; TableInformation tableInformation = null;
while ( resultSet.next() ) { while ( resultSet.next() ) {
if ( tableName.equals( Identifier.toIdentifier( final Identifier identifier =
resultSet.getString( getResultSetTableNameLabel() ), toIdentifier( resultSet.getString( getResultSetTableNameLabel() ),
tableName.isQuoted() tableName.isQuoted() );
) ) ) { if ( tableName.equals( identifier ) ) {
if ( found ) { if ( found ) {
LOG.multipleTablesFound( tableName.render() ); LOG.multipleTablesFound( tableName.render() );
throw new SchemaExtractionException( throw new SchemaExtractionException(
@ -867,7 +852,7 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
"%", "%",
resultSet -> { resultSet -> {
while ( resultSet.next() ) { while ( resultSet.next() ) {
addExtractedColumnInformation( tableInformation, resultSet ); tableInformation.addColumn( columnInformation( tableInformation, resultSet ) );
} }
return null; 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) { private Boolean interpretTruthValue(String nullable) {
if ( "yes".equalsIgnoreCase( nullable ) ) { if ( "yes".equalsIgnoreCase( nullable ) ) {
return Boolean.TRUE; return Boolean.TRUE;
@ -904,7 +881,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
String catalogFilter, String catalogFilter,
String schemaFilter, String schemaFilter,
Identifier tableName, Identifier tableName,
ExtractionContext.ResultSetProcessor<T> processor) throws SQLException; ExtractionContext.ResultSetProcessor<T> processor)
throws SQLException;
@Override @Override
public PrimaryKeyInformation getPrimaryKey(TableInformationImpl tableInformation) { public PrimaryKeyInformation getPrimaryKey(TableInformationImpl tableInformation) {
@ -926,10 +904,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
} }
} }
private PrimaryKeyInformation extractPrimaryKeyInformation( private PrimaryKeyInformation extractPrimaryKeyInformation(TableInformation tableInformation, ResultSet resultSet)
TableInformation tableInformation, throws SQLException {
ResultSet resultSet
) throws SQLException {
final List<ColumnInformation> pkColumns = new ArrayList<>(); final List<ColumnInformation> pkColumns = new ArrayList<>();
boolean firstPass = true; boolean firstPass = true;
@ -937,19 +913,16 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
while ( resultSet.next() ) { while ( resultSet.next() ) {
final String currentPkName = resultSet.getString( getResultSetPrimaryKeyNameLabel() ); final String currentPkName = resultSet.getString( getResultSetPrimaryKeyNameLabel() );
final Identifier currentPkIdentifier = currentPkName == null ? null : toIdentifier( currentPkName ); final Identifier currentPkIdentifier =
currentPkName == null ? null : toIdentifier( currentPkName );
if ( firstPass ) { if ( firstPass ) {
pkIdentifier = currentPkIdentifier; pkIdentifier = currentPkIdentifier;
firstPass = false; firstPass = false;
} }
else { else {
if ( !Objects.equals( pkIdentifier, currentPkIdentifier ) ) { if ( !Objects.equals( pkIdentifier, currentPkIdentifier ) ) {
throw new SchemaExtractionException( throw new SchemaExtractionException( "Encountered primary keys differing name on table "
String.format( + tableInformation.getName().toString() );
"Encountered primary keys differing name on table %s",
tableInformation.getName().toString()
)
);
} }
} }
@ -1054,7 +1027,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
String table, String table,
boolean unique, boolean unique,
boolean approximate, boolean approximate,
ExtractionContext.ResultSetProcessor<T> processor) throws SQLException; ExtractionContext.ResultSetProcessor<T> processor)
throws SQLException;
@Override @Override
public Iterable<IndexInformation> getIndexes(TableInformation tableInformation) { public Iterable<IndexInformation> getIndexes(TableInformation tableInformation) {
@ -1186,8 +1160,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
String catalog, String catalog,
String schema, String schema,
String table, String table,
ExtractionContext.ResultSetProcessor<T> processor ExtractionContext.ResultSetProcessor<T> processor)
) throws SQLException; throws SQLException;
/** /**
* Must do the following: * Must do the following:
@ -1271,8 +1245,8 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
String foreignCatalog, String foreignCatalog,
String foreignSchema, String foreignSchema,
String foreignTable, String foreignTable,
ExtractionContext.ResultSetProcessor<T> processor ExtractionContext.ResultSetProcessor<T> processor)
) throws SQLException; throws SQLException;
@Override @Override
@ -1322,8 +1296,11 @@ public abstract class AbstractInformationExtractorImpl implements InformationExt
return fks; return fks;
} }
private void process(TableInformation tableInformation, ResultSet resultSet, Map<Identifier, ForeignKeyBuilder> fkBuilders) private void process(
throws SQLException { TableInformation tableInformation,
ResultSet resultSet,
Map<Identifier, ForeignKeyBuilder> fkBuilders)
throws SQLException {
while ( resultSet.next() ) { while ( resultSet.next() ) {
// IMPL NOTE : The builder is mainly used to collect the column reference mappings // IMPL NOTE : The builder is mainly used to collect the column reference mappings
final Identifier fkIdentifier = toIdentifier( resultSet.getString( getResultSetForeignKeyLabel() ) ); final Identifier fkIdentifier = toIdentifier( resultSet.getString( getResultSetForeignKeyLabel() ) );

View File

@ -39,8 +39,9 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
} }
@Override @Override
public <T> T processCatalogsResultSet(ExtractionContext.ResultSetProcessor<T> processor) throws SQLException { public <T> T processCatalogsResultSet(ExtractionContext.ResultSetProcessor<T> processor)
try (ResultSet resultSet = getJdbcDatabaseMetaData().getCatalogs() ) { throws SQLException {
try ( ResultSet resultSet = getJdbcDatabaseMetaData().getCatalogs() ) {
return processor.process( resultSet ); return processor.process( resultSet );
} }
} }
@ -49,10 +50,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
protected <T> T processSchemaResultSet( protected <T> T processSchemaResultSet(
String catalog, String catalog,
String schemaPattern, String schemaPattern,
ExtractionContext.ResultSetProcessor<T> processor) throws SQLException { ExtractionContext.ResultSetProcessor<T> processor)
try (ResultSet resultSet = getJdbcDatabaseMetaData().getSchemas( throws SQLException {
catalog, try ( ResultSet resultSet =
schemaPattern ) ) { getJdbcDatabaseMetaData()
.getSchemas( catalog, schemaPattern ) ) {
return processor.process( resultSet ); return processor.process( resultSet );
} }
} }
@ -63,13 +65,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
String schemaPattern, String schemaPattern,
String tableNamePattern, String tableNamePattern,
String[] types, String[] types,
ExtractionContext.ResultSetProcessor<T> processor ExtractionContext.ResultSetProcessor<T> processor)
) throws SQLException { throws SQLException {
try (ResultSet resultSet = getJdbcDatabaseMetaData().getTables( try ( ResultSet resultSet =
catalog, getJdbcDatabaseMetaData()
schemaPattern, .getTables( catalog, schemaPattern, tableNamePattern, types) ) {
tableNamePattern,
types)) {
return processor.process( resultSet ); return processor.process( resultSet );
} }
} }
@ -80,12 +80,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
String schemaPattern, String schemaPattern,
String tableNamePattern, String tableNamePattern,
String columnNamePattern, String columnNamePattern,
ExtractionContext.ResultSetProcessor<T> processor) throws SQLException { ExtractionContext.ResultSetProcessor<T> processor)
try (ResultSet resultSet = getJdbcDatabaseMetaData().getColumns( throws SQLException {
catalog, try ( ResultSet resultSet =
schemaPattern, getJdbcDatabaseMetaData()
tableNamePattern, .getColumns( catalog, schemaPattern, tableNamePattern, columnNamePattern ) ) {
columnNamePattern )) {
return processor.process( resultSet ); return processor.process( resultSet );
} }
} }
@ -95,11 +94,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
String catalogFilter, String catalogFilter,
String schemaFilter, String schemaFilter,
Identifier tableName, Identifier tableName,
ExtractionContext.ResultSetProcessor<T> processor) throws SQLException { ExtractionContext.ResultSetProcessor<T> processor)
try( ResultSet resultSet = getJdbcDatabaseMetaData().getPrimaryKeys( throws SQLException {
catalogFilter, try ( ResultSet resultSet =
schemaFilter, getJdbcDatabaseMetaData()
tableName.getText() ) ) { .getPrimaryKeys( catalogFilter, schemaFilter, tableName.getText() ) ) {
return processor.process( resultSet ); return processor.process( resultSet );
} }
} }
@ -111,14 +110,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
String table, String table,
boolean unique, boolean unique,
boolean approximate, boolean approximate,
ExtractionContext.ResultSetProcessor<T> processor) throws SQLException { ExtractionContext.ResultSetProcessor<T> processor)
throws SQLException {
try (ResultSet resultSet = getJdbcDatabaseMetaData().getIndexInfo( try ( ResultSet resultSet =
catalog, getJdbcDatabaseMetaData()
schema, .getIndexInfo( catalog, schema, table, unique, approximate ) ) {
table,
unique,
approximate ) ) {
return processor.process( resultSet ); return processor.process( resultSet );
} }
} }
@ -128,11 +124,11 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
String catalog, String catalog,
String schema, String schema,
String table, String table,
ExtractionContext.ResultSetProcessor<T> processor) throws SQLException { ExtractionContext.ResultSetProcessor<T> processor)
try (ResultSet resultSet = getJdbcDatabaseMetaData().getImportedKeys( throws SQLException {
catalog, try ( ResultSet resultSet =
schema, getJdbcDatabaseMetaData()
table ) ) { .getImportedKeys( catalog, schema, table ) ) {
return processor.process( resultSet ); return processor.process( resultSet );
} }
} }
@ -145,14 +141,12 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
String foreignCatalog, String foreignCatalog,
String foreignSchema, String foreignSchema,
String foreignTable, String foreignTable,
ExtractionContext.ResultSetProcessor<T> processor) throws SQLException { ExtractionContext.ResultSetProcessor<T> processor)
try (ResultSet resultSet = getJdbcDatabaseMetaData().getCrossReference( throws SQLException {
parentCatalog, try ( ResultSet resultSet =
parentSchema, getJdbcDatabaseMetaData()
parentTable, .getCrossReference( parentCatalog, parentSchema, parentTable,
foreignCatalog, foreignCatalog, foreignSchema, foreignTable) ) {
foreignSchema,
foreignTable) ) {
return processor.process( resultSet ); return processor.process( resultSet );
} }
} }
@ -162,12 +156,12 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
final ExtractionContext extractionContext = getExtractionContext(); final ExtractionContext extractionContext = getExtractionContext();
// We use this dummy query to retrieve the table information through the ResultSetMetaData // 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 // Significantly better than using DatabaseMetaData especially on Oracle with synonyms enabled
final String tableName = extractionContext.getSqlStringGenerationContext().format( final String tableName =
// The name comes from the database, so the case is correct extractionContext.getSqlStringGenerationContext()
// But we quote here to avoid issues with reserved words // The name comes from the database, so the case is correct
tableInformation.getName().quote() // But we quote here to avoid issues with reserved words
); .format( tableInformation.getName().quote() );
try { try {
extractionContext.getQueryResults( extractionContext.getQueryResults(
@ -176,38 +170,51 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl extends AbstractInform
resultSet -> { resultSet -> {
final ResultSetMetaData metaData = resultSet.getMetaData(); final ResultSetMetaData metaData = resultSet.getMetaData();
final int columnCount = metaData.getColumnCount(); final int columnCount = metaData.getColumnCount();
for ( int i = 1; i <= columnCount; i++ ) { for ( int i = 1; i <= columnCount; i++ ) {
final String columnName = metaData.getColumnName( i ); tableInformation.addColumn( columnInformation( tableInformation, metaData, i, dialect ) );
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 );
} }
return null; return null;
} }
); );
} }
catch (SQLException e) { catch (SQLException e) {
throw convertSQLException( throw convertSQLException( e,
e, "Error accessing column metadata: "
"Error accessing column metadata: " + tableInformation.getName().toString() + 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 ) )
);
}
} }

View File

@ -35,7 +35,7 @@ public class TableInformationImpl implements TableInformation {
private PrimaryKeyInformation primaryKey; private PrimaryKeyInformation primaryKey;
private Map<Identifier, ForeignKeyInformation> foreignKeys; private Map<Identifier, ForeignKeyInformation> foreignKeys;
private Map<Identifier, IndexInformation> indexes; private Map<Identifier, IndexInformation> indexes;
private Map<Identifier, ColumnInformation> columns = new HashMap<>( ); private final Map<Identifier, ColumnInformation> columns = new HashMap<>();
private boolean wasPrimaryKeyLoaded = false; // to avoid multiple db reads since primary key can be null. private boolean wasPrimaryKeyLoaded = false; // to avoid multiple db reads since primary key can be null.