HHH-9849 - Fix Duplicate column name for mixed case column name on schema update

This commit is contained in:
Andrea Boriero 2015-06-16 16:31:15 +01:00
parent 9024ff55d6
commit d29b55a31a
9 changed files with 40 additions and 228 deletions

View File

@ -188,79 +188,4 @@ public class NormalizingIdentifierHelperImpl implements IdentifierHelper {
} }
return toMetaDataText( identifier ); return toMetaDataText( identifier );
} }
@Override
public Identifier fromMetaDataCatalogName(String catalogName) {
if ( catalogName == null || !nameQualifierSupport.supportsCatalogs() ) {
return null;
}
// if ( jdbcEnvironment.getCurrentCatalog() == null
// || catalogName.equals( jdbcEnvironment.getCurrentCatalog().getText() ) ) {
// return null;
// }
return toIdentifierFromMetaData( catalogName );
}
public Identifier toIdentifierFromMetaData(String text) {
log.tracef( "Interpreting return value [%s] from DatabaseMetaData as identifier", text );
if ( globallyQuoteIdentifiers ) {
log.trace( "Forcing DatabaseMetaData return value as quoted due to global quoting" );
return Identifier.toIdentifier( text, true );
}
if ( autoQuoteKeywords && isReservedWord( text ) ) {
// unequivocally it needs to be quoted...
log.trace( "Forcing DatabaseMetaData return value as quoted as it was recognized as a reserved word" );
return Identifier.toIdentifier( text, true );
}
// lovely decipher of whether the incoming value represents a quoted identifier...
final boolean isUpperCase = text.toUpperCase( Locale.ROOT ).equals( text );
final boolean isLowerCase = text.toLowerCase( Locale.ROOT ).equals( text );
final boolean isMixedCase = ! isLowerCase && ! isUpperCase;
if ( quotedCaseStrategy == IdentifierCaseStrategy.MIXED && isMixedCase ) {
log.trace( "Interpreting return value as quoted due to case strategy" );
return Identifier.toIdentifier( text, true );
}
if ( quotedCaseStrategy == IdentifierCaseStrategy.LOWER && isLowerCase ) {
log.trace( "Interpreting return value as quoted due to case strategy" );
return Identifier.toIdentifier( text, true );
}
if ( quotedCaseStrategy == IdentifierCaseStrategy.UPPER && isUpperCase ) {
log.trace( "Interpreting return value as quoted due to case strategy" );
return Identifier.toIdentifier( text, true );
}
log.trace( "Interpreting return value as unquoted due to case strategy" );
return Identifier.toIdentifier( text );
}
@Override
public Identifier fromMetaDataSchemaName(String schemaName) {
if ( schemaName == null || !nameQualifierSupport.supportsSchemas() ) {
return null;
}
// if ( jdbcEnvironment.getCurrentSchema() == null
// || schemaName.equals( jdbcEnvironment.getCurrentSchema().getText() ) ) {
// return null;
// }
return toIdentifierFromMetaData( schemaName );
}
@Override
public Identifier fromMetaDataObjectName(String objectName) {
if ( objectName == null ) {
return null;
}
return toIdentifierFromMetaData( objectName );
}
} }

View File

@ -101,34 +101,4 @@ public interface IdentifierHelper {
* @return The String representation of the given object name * @return The String representation of the given object name
*/ */
String toMetaDataObjectName(Identifier identifier); String toMetaDataObjectName(Identifier identifier);
/**
* Parse an Identifier representation from the String representation of a catalog name
* as obtained from {@link java.sql.DatabaseMetaData} calls.
*
* @param catalogName The String representation of a catalog name
*
* @return The parsed Identifier representation of the given catalog name
*/
Identifier fromMetaDataCatalogName(String catalogName);
/**
* Parse an Identifier representation from the String representation of a schema name
* as obtained from {@link java.sql.DatabaseMetaData} calls.
*
* @param schemaName The String representation of a schema name
*
* @return The parsed Identifier representation of the given schema name
*/
Identifier fromMetaDataSchemaName(String schemaName);
/**
* Parse an Identifier representation from the String representation of an object name
* as obtained from {@link java.sql.DatabaseMetaData} calls.
*
* @param name The String representation of an object name
*
* @return The parsed Identifier representation of the given object name
*/
Identifier fromMetaDataObjectName(String name);
} }

View File

@ -10,7 +10,6 @@ import java.sql.DatabaseMetaData;
import java.sql.ResultSet; import java.sql.ResultSet;
import java.sql.SQLException; import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@ -106,46 +105,6 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
} }
} }
@Override
public Collection<TableInformation> getTables(Identifier catalog, Identifier schema) {
try {
final String catalogFilter = determineCatalogFilter( catalog );
final String schemaFilter = determineSchemaFilter( schema );
final List<TableInformation> results = new ArrayList<TableInformation>();
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getTables(
catalogFilter,
schemaFilter,
null,
tableTypes
);
try {
while ( resultSet.next() ) {
final TableInformation tableInformation = extractTableInformation(
catalog,
schema,
null,
resultSet
);
results.add( tableInformation );
}
}
finally {
try {
resultSet.close();
}
catch (SQLException ignore) {
}
}
return results;
}
catch (SQLException sqlException) {
throw convertSQLException( sqlException, "Error accessing table metadata" );
}
}
private String determineCatalogFilter(Identifier catalog) throws SQLException { private String determineCatalogFilter(Identifier catalog) throws SQLException {
Identifier identifierToUse = catalog; Identifier identifierToUse = catalog;
if ( identifierToUse == null ) { if ( identifierToUse == null ) {
@ -170,13 +129,13 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
Identifier name, Identifier name,
ResultSet resultSet) throws SQLException { ResultSet resultSet) throws SQLException {
if ( catalog == null ) { if ( catalog == null ) {
catalog = identifierHelper().fromMetaDataCatalogName( resultSet.getString( "TABLE_CAT" ) ); catalog = identifierHelper().toIdentifier( resultSet.getString( "TABLE_CAT" ) );
} }
if ( schema == null ) { if ( schema == null ) {
schema = identifierHelper().fromMetaDataSchemaName( resultSet.getString( "TABLE_SCHEM" ) ); schema = identifierHelper().toIdentifier( resultSet.getString( "TABLE_SCHEM" ) );
} }
if ( name == null ) { if ( name == null ) {
name = identifierHelper().fromMetaDataObjectName( resultSet.getString( "TABLE_NAME" ) ); name = identifierHelper().toIdentifier( resultSet.getString( "TABLE_NAME" ) );
} }
final QualifiedTableName tableName = new QualifiedTableName( catalog, schema, name ); final QualifiedTableName tableName = new QualifiedTableName( catalog, schema, name );
@ -239,36 +198,31 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
} }
@Override @Override
public Iterable<ColumnInformation> getColumns(TableInformation tableInformation) { public ColumnInformation getColumn(TableInformation tableInformation, Identifier columnIdentifier) {
final List<ColumnInformation> results = new ArrayList<ColumnInformation>();
try { try {
ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getColumns( ResultSet resultSet = extractionContext.getJdbcDatabaseMetaData().getColumns(
identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalogName() ), identifierHelper().toMetaDataCatalogName( tableInformation.getName().getCatalogName() ),
identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchemaName() ), identifierHelper().toMetaDataSchemaName( tableInformation.getName().getSchemaName() ),
identifierHelper().toMetaDataObjectName( tableInformation.getName().getTableName() ), identifierHelper().toMetaDataObjectName( tableInformation.getName().getTableName() ),
"%" extractionContext.getJdbcEnvironment()
.getIdentifierHelper()
.toMetaDataObjectName( columnIdentifier )
); );
try { try {
while ( resultSet.next() ) { if ( !resultSet.next() ) {
final String columnName = resultSet.getString( "COLUMN_NAME" ); return null;
if ( columnName == null ) {
continue;
} }
return new ColumnInformationImpl(
results.add(
new ColumnInformationImpl(
tableInformation, tableInformation,
identifierHelper().fromMetaDataObjectName( columnName ), identifierHelper().toIdentifier( resultSet.getString( "COLUMN_NAME" ) ),
resultSet.getInt( "DATA_TYPE" ), resultSet.getInt( "DATA_TYPE" ),
new StringTokenizer( resultSet.getString( "TYPE_NAME" ), "() " ).nextToken(), new StringTokenizer( resultSet.getString( "TYPE_NAME" ), "() " ).nextToken(),
resultSet.getInt( "COLUMN_SIZE" ), resultSet.getInt( "COLUMN_SIZE" ),
resultSet.getInt( "DECIMAL_DIGITS" ), resultSet.getInt( "DECIMAL_DIGITS" ),
interpretTruthValue( resultSet.getString( "IS_NULLABLE" ) ) interpretTruthValue( resultSet.getString( "IS_NULLABLE" ) )
)
); );
}
} }
finally { finally {
resultSet.close(); resultSet.close();
@ -277,8 +231,6 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
catch (SQLException e) { catch (SQLException e) {
throw convertSQLException( e, "Error accessing column metadata: " + tableInformation.getName().toString() ); throw convertSQLException( e, "Error accessing column metadata: " + tableInformation.getName().toString() );
} }
return results;
} }
private TruthValue interpretTruthValue(String nullable) { private TruthValue interpretTruthValue(String nullable) {
@ -309,7 +261,7 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
final String currentPkName = resultSet.getString( "PK_NAME" ); final String currentPkName = resultSet.getString( "PK_NAME" );
final Identifier currentPkIdentifier = currentPkName == null final Identifier currentPkIdentifier = currentPkName == null
? null ? null
: identifierHelper().fromMetaDataObjectName( currentPkName ); : identifierHelper().toIdentifier( currentPkName );
if ( firstPass ) { if ( firstPass ) {
pkIdentifier = currentPkIdentifier; pkIdentifier = currentPkIdentifier;
firstPass = false; firstPass = false;
@ -328,7 +280,7 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
final int columnPosition = resultSet.getInt( "KEY_SEQ" ); final int columnPosition = resultSet.getInt( "KEY_SEQ" );
final String columnName = resultSet.getString( "COLUMN_NAME" ); final String columnName = resultSet.getString( "COLUMN_NAME" );
final Identifier columnIdentifier = identifierHelper().fromMetaDataObjectName( columnName ); final Identifier columnIdentifier = identifierHelper().toIdentifier( columnName );
final ColumnInformation column = tableInformation.getColumn( columnIdentifier ); final ColumnInformation column = tableInformation.getColumn( columnIdentifier );
pkColumns.add( columnPosition-1, column ); pkColumns.add( columnPosition-1, column );
} }
@ -377,7 +329,7 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
continue; continue;
} }
final Identifier indexIdentifier = identifierHelper().fromMetaDataObjectName( final Identifier indexIdentifier = identifierHelper().toIdentifier(
resultSet.getString( resultSet.getString(
"INDEX_NAME" "INDEX_NAME"
) )
@ -388,7 +340,7 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
builders.put( indexIdentifier, builder ); builders.put( indexIdentifier, builder );
} }
final Identifier columnIdentifier = identifierHelper().fromMetaDataObjectName( resultSet.getString( "COLUMN_NAME" ) ); final Identifier columnIdentifier = identifierHelper().toIdentifier( resultSet.getString( "COLUMN_NAME" ) );
final ColumnInformation columnInformation = tableInformation.getColumn( columnIdentifier ); final ColumnInformation columnInformation = tableInformation.getColumn( columnIdentifier );
if ( columnInformation == null ) { if ( columnInformation == null ) {
throw new SchemaManagementException( throw new SchemaManagementException(
@ -433,7 +385,7 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
try { try {
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 = identifierHelper().fromMetaDataObjectName( final Identifier fkIdentifier = identifierHelper().toIdentifier(
resultSet.getString( "FK_NAME" ) resultSet.getString( "FK_NAME" )
); );
ForeignKeyBuilder fkBuilder = fkBuilders.get( fkIdentifier ); ForeignKeyBuilder fkBuilder = fkBuilders.get( fkIdentifier );
@ -455,10 +407,10 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
continue; continue;
} }
final Identifier fkColumnIdentifier = identifierHelper().fromMetaDataObjectName( final Identifier fkColumnIdentifier = identifierHelper().toIdentifier(
resultSet.getString( "FKCOLUMN_NAME" ) resultSet.getString( "FKCOLUMN_NAME" )
); );
final Identifier pkColumnIdentifier = identifierHelper().fromMetaDataObjectName( final Identifier pkColumnIdentifier = identifierHelper().toIdentifier(
resultSet.getString( "PKCOLUMN_NAME" ) resultSet.getString( "PKCOLUMN_NAME" )
); );
@ -529,9 +481,9 @@ public class InformationExtractorJdbcDatabaseMetaDataImpl implements Information
final String incomingTableName = resultSet.getString( prefix + "TABLE_NAME" ); final String incomingTableName = resultSet.getString( prefix + "TABLE_NAME" );
return new QualifiedTableName( return new QualifiedTableName(
identifierHelper().fromMetaDataCatalogName( incomingCatalogName ), identifierHelper().toIdentifier( incomingCatalogName ),
identifierHelper().fromMetaDataSchemaName( incomingSchemaName ), identifierHelper().toIdentifier( incomingSchemaName ),
identifierHelper().fromMetaDataObjectName( incomingTableName ) identifierHelper().toIdentifier( incomingTableName )
); );
} }
} }

View File

@ -44,13 +44,13 @@ public class SequenceInformationExtractorH2DatabaseImpl implements SequenceInfor
sequenceInformationList.add( sequenceInformationList.add(
new SequenceInformationImpl( new SequenceInformationImpl(
new QualifiedSequenceName( new QualifiedSequenceName(
identifierHelper.fromMetaDataCatalogName( identifierHelper.toIdentifier(
resultSet.getString( "SEQUENCE_CATALOG" ) resultSet.getString( "SEQUENCE_CATALOG" )
), ),
identifierHelper.fromMetaDataSchemaName( identifierHelper.toIdentifier(
resultSet.getString( "SEQUENCE_SCHEMA" ) resultSet.getString( "SEQUENCE_SCHEMA" )
), ),
identifierHelper.fromMetaDataObjectName( identifierHelper.toIdentifier(
resultSet.getString( "SEQUENCE_NAME" ) resultSet.getString( "SEQUENCE_NAME" )
) )
), ),

View File

@ -48,7 +48,7 @@ public class SequenceInformationExtractorLegacyImpl implements SequenceInformati
new QualifiedSequenceName( new QualifiedSequenceName(
null, null,
null, null,
identifierHelper.fromMetaDataObjectName( identifierHelper.toIdentifier(
resultSet.getString( 1 ) resultSet.getString( 1 )
) )
), ),

View File

@ -31,7 +31,6 @@ public class TableInformationImpl implements TableInformation {
private final boolean physicalTable; private final boolean physicalTable;
private final String comment; private final String comment;
private Map<Identifier, ColumnInformation> columns;
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;
@ -64,26 +63,9 @@ public class TableInformationImpl implements TableInformation {
return comment; 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 = extractor.getColumns( this );
for ( ColumnInformation columnInformation : columnInformationItr ) {
columnMap.put( columnInformation.getColumnIdentifier(), columnInformation );
}
this.columns = columnMap;
}
return this.columns;
}
@Override @Override
public ColumnInformation getColumn(Identifier columnIdentifier) { public ColumnInformation getColumn(Identifier columnIdentifier) {
return columns().get( columnIdentifier ); return extractor.getColumn( this, columnIdentifier );
} }
@Override @Override

View File

@ -25,19 +25,6 @@ public interface InformationExtractor {
boolean schemaExists(Identifier catalog, Identifier schema); boolean schemaExists(Identifier catalog, Identifier schema);
/**
* Return information about all matching tables, depending on whether to apply filter for
* catalog/schema.
*
* @param catalog Can be {@code null}, indicating that any catalog may be considered a match. A
* non-{@code null} value indicates that search should be limited to the passed catalog.
* @param schema Can be {@code null}, indicating that any schema may be considered a match. A
* non-{@code null} value indicates that search should be limited to the passed schema .
*
* @return The matching table information
*/
public Collection<TableInformation> getTables(Identifier catalog, Identifier schema);
/** /**
* Look for a matching table. * Look for a matching table.
* *
@ -52,14 +39,15 @@ public interface InformationExtractor {
public TableInformation getTable(Identifier catalog, Identifier schema, Identifier tableName); public TableInformation getTable(Identifier catalog, Identifier schema, Identifier tableName);
/** /**
* Return information about columns for the given table. Typically called from the TableInformation itself * Return information about column for the given table. Typically called from the TableInformation itself
* as part of on-demand initialization of its state. * as part of on-demand initialization of its state.
* *
* @param tableInformation The table for which to locate columns * @param tableInformation table info for the matching table
* @param columnIdentifier The column identifier for which to locate column
* *
* @return The extracted column information * @return The extracted column information
*/ */
public Iterable<ColumnInformation> getColumns(TableInformation tableInformation); public ColumnInformation getColumn(TableInformation tableInformation, Identifier columnIdentifier);
/** /**
* Extract information about the given table's primary key. * Extract information about the given table's primary key.

View File

@ -38,13 +38,6 @@ public interface TableInformation {
*/ */
public String getComment(); 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 * Retrieve the named ColumnInformation
* *

View File

@ -36,6 +36,7 @@ public class TargetDatabaseImpl implements Target {
public void prepare() { public void prepare() {
try { try {
connection = connectionAccess.obtainConnection(); connection = connectionAccess.obtainConnection();
connection.setAutoCommit( true );
} }
catch (SQLException e) { catch (SQLException e) {
throw new SchemaManagementException( "Unable to open JDBC connection for schema management target", e ); throw new SchemaManagementException( "Unable to open JDBC connection for schema management target", e );
@ -70,6 +71,7 @@ public class TargetDatabaseImpl implements Target {
} }
if ( connection != null ) { if ( connection != null ) {
try { try {
connectionAccess.releaseConnection( connection ); connectionAccess.releaseConnection( connection );
} }
catch (SQLException ignore) { catch (SQLException ignore) {