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

View File

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

View File

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

View File

@ -31,7 +31,6 @@ public class TableInformationImpl implements TableInformation {
private final boolean physicalTable;
private final String comment;
private Map<Identifier, ColumnInformation> columns;
private PrimaryKeyInformation primaryKey;
private Map<Identifier, ForeignKeyInformation> foreignKeys;
private Map<Identifier, IndexInformation> indexes;
@ -64,26 +63,9 @@ public class TableInformationImpl implements TableInformation {
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
public ColumnInformation getColumn(Identifier columnIdentifier) {
return columns().get( columnIdentifier );
return extractor.getColumn( this, columnIdentifier );
}
@Override

View File

@ -25,19 +25,6 @@ public interface InformationExtractor {
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.
*
@ -52,14 +39,15 @@ public interface InformationExtractor {
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.
*
* @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
*/
public Iterable<ColumnInformation> getColumns(TableInformation tableInformation);
public ColumnInformation getColumn(TableInformation tableInformation, Identifier columnIdentifier);
/**
* Extract information about the given table's primary key.

View File

@ -38,13 +38,6 @@ public interface TableInformation {
*/
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
*

View File

@ -36,6 +36,7 @@ public class TargetDatabaseImpl implements Target {
public void prepare() {
try {
connection = connectionAccess.obtainConnection();
connection.setAutoCommit( true );
}
catch (SQLException 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 ) {
try {
connectionAccess.releaseConnection( connection );
}
catch (SQLException ignore) {