From dbcf8b436957daf93965f298617e37f5de0bad12 Mon Sep 17 00:00:00 2001 From: "nathan.voxland" Date: Sat, 18 Aug 2012 00:14:18 -0500 Subject: [PATCH 01/11] CORE-857 Generation of invalid SQL statement from generated diff --- .../main/java/liquibase/database/structure/DataType.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/liquibase-core/src/main/java/liquibase/database/structure/DataType.java b/liquibase-core/src/main/java/liquibase/database/structure/DataType.java index e813693f554..67f9c948e04 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/DataType.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/DataType.java @@ -70,6 +70,11 @@ public void setAutoIncrementInformation(AutoIncrementInformation autoIncrementIn @Override public String toString() { String value = typeName; + boolean unsigned = false; + if (value.toLowerCase().endsWith(" unsigned")) { + value = value.substring(0, value.length()-" unsigned".length()); + unsigned = true; + } if (columnSize != null) { value += "("; @@ -82,6 +87,10 @@ public String toString() { value +=")"; } + if (unsigned) { + value += " UNSIGNED"; + } + return value; } From e565c11675824b3709b9233fe8d59384f2223f31 Mon Sep 17 00:00:00 2001 From: "nathan.voxland" Date: Sat, 18 Aug 2012 00:38:30 -0500 Subject: [PATCH 02/11] CORE-851 generateChangeLog creates indexes belonging to another owner on Oracle10g database --- .../jvm/OracleDatabaseSnapshotGenerator.java | 193 +++++++++--------- 1 file changed, 97 insertions(+), 96 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java index 4de5b8a8d4b..383dfe6429b 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java @@ -284,102 +284,103 @@ public int getPriority(Database database) { // return foreignKeys; // } // -// @Override -// protected void readIndexes(DatabaseSnapshot snapshot, String schema, DatabaseMetaData databaseMetaData) throws DatabaseException, SQLException { -// Database database = snapshot.getDatabase(); -// updateListeners("Reading indexes for " + database.toString() + " ..."); -// -// String query = "select aic.index_name, 3 AS TYPE, aic.table_name, aic.column_name, aic.column_position AS ORDINAL_POSITION, null AS FILTER_CONDITION, ai.tablespace_name AS TABLESPACE, ai.uniqueness FROM all_ind_columns aic, all_indexes ai WHERE aic.table_owner='" + database.convertRequestedSchemaToSchema(schema) + "' and aic.index_name = ai.index_name ORDER BY INDEX_NAME, ORDINAL_POSITION"; -// Statement statement = null; -// ResultSet rs = null; -// Map indexMap = null; -// try { -// statement = ((JdbcConnection) database.getConnection()).getUnderlyingConnection().createStatement(); -// rs = statement.executeQuery(query); -// -// indexMap = new HashMap(); -// while (rs.next()) { -// String indexName = cleanObjectNameFromDatabase(rs.getString("INDEX_NAME")); -// String tableName = rs.getString("TABLE_NAME"); -// String tableSpace = rs.getString("TABLESPACE"); -// String columnName = cleanObjectNameFromDatabase(rs.getString("COLUMN_NAME")); -// if (columnName == null) { -// //nothing to index, not sure why these come through sometimes -// continue; -// } -// short type = rs.getShort("TYPE"); -// -// boolean nonUnique; -// -// String uniqueness = rs.getString("UNIQUENESS"); -// -// if ("UNIQUE".equals(uniqueness)) { -// nonUnique = false; -// } else { -// nonUnique = true; -// } -// -// short position = rs.getShort("ORDINAL_POSITION"); -// String filterCondition = rs.getString("FILTER_CONDITION"); -// -// if (type == DatabaseMetaData.tableIndexStatistic) { -// continue; -// } -// -// Index index; -// if (indexMap.containsKey(indexName)) { -// index = indexMap.get(indexName); -// } else { -// index = new Index(); -// Table table = snapshot.getTable(tableName); -// if (table == null) { -// continue; //probably different schema -// } -// index.setTable(table); -// index.setTablespace(tableSpace); -// index.setName(indexName); -// index.setUnique(!nonUnique); -// index.setFilterCondition(filterCondition); -// indexMap.put(indexName, index); -// } -// -// for (int i = index.getColumns().size(); i < position; i++) { -// index.getColumns().add(null); -// } -// index.getColumns().set(position - 1, columnName); -// } -// } finally { -// JdbcUtils.closeResultSet(rs); -// JdbcUtils.closeStatement(statement); -// } -// -// for (Map.Entry entry : indexMap.entrySet()) { -// snapshot.getIndexes().add(entry.getValue()); -// } -// -// /* -// * marks indexes as "associated with" instead of "remove it" -// * Index should have associations with: -// * foreignKey, primaryKey or uniqueConstraint -// * */ -// for (Index index : snapshot.getIndexes()) { -// for (PrimaryKey pk : snapshot.getPrimaryKeys()) { -// if (index.getTable().getName().equalsIgnoreCase(pk.getTable().getName()) && index.getColumnNames().equals(pk.getColumnNames())) { -// index.addAssociatedWith(Index.MARK_PRIMARY_KEY); -// } -// } -// for (ForeignKey fk : snapshot.getForeignKeys()) { -// if (index.getTable().getName().equalsIgnoreCase(fk.getForeignKeyTable().getName()) && index.getColumnNames().equals(fk.getForeignKeyColumns())) { -// index.addAssociatedWith(Index.MARK_FOREIGN_KEY); -// } -// } -// for (UniqueConstraint uc : snapshot.getUniqueConstraints()) { -// if (index.getTable().getName().equalsIgnoreCase(uc.getTable().getName()) && index.getColumnNames().equals(uc.getColumnNames())) { -// index.addAssociatedWith(Index.MARK_UNIQUE_CONSTRAINT); -// } -// } -// } -// } + @Override + protected void readIndexes(DatabaseSnapshot snapshot, Schema schema, DatabaseMetaData databaseMetaData) throws DatabaseException, SQLException { + Database database = snapshot.getDatabase(); + schema = database.correctSchema(schema); + updateListeners("Reading indexes for " + database.toString() + " ..."); + + String query = "select aic.index_name, 3 AS TYPE, aic.table_name, aic.column_name, aic.column_position AS ORDINAL_POSITION, null AS FILTER_CONDITION, ai.tablespace_name AS TABLESPACE, ai.uniqueness FROM all_ind_columns aic, all_indexes ai WHERE aic.table_owner='" + schema.getName() + "' and ai.table_owner='" + schema.getName() + "' and aic.index_name = ai.index_name ORDER BY INDEX_NAME, ORDINAL_POSITION"; + Statement statement = null; + ResultSet rs = null; + Map indexMap = null; + try { + statement = ((JdbcConnection) database.getConnection()).getUnderlyingConnection().createStatement(); + rs = statement.executeQuery(query); + + indexMap = new HashMap(); + while (rs.next()) { + String indexName = cleanObjectNameFromDatabase(rs.getString("INDEX_NAME")); + String tableName = rs.getString("TABLE_NAME"); + String tableSpace = rs.getString("TABLESPACE"); + String columnName = cleanObjectNameFromDatabase(rs.getString("COLUMN_NAME")); + if (columnName == null) { + //nothing to index, not sure why these come through sometimes + continue; + } + short type = rs.getShort("TYPE"); + + boolean nonUnique; + + String uniqueness = rs.getString("UNIQUENESS"); + + if ("UNIQUE".equals(uniqueness)) { + nonUnique = false; + } else { + nonUnique = true; + } + + short position = rs.getShort("ORDINAL_POSITION"); + String filterCondition = rs.getString("FILTER_CONDITION"); + + if (type == DatabaseMetaData.tableIndexStatistic) { + continue; + } + + Index index; + if (indexMap.containsKey(indexName)) { + index = indexMap.get(indexName); + } else { + index = new Index(); + Table table = snapshot.getDatabaseObject(schema, tableName, Table.class); + if (table == null) { + continue; //probably different schema + } + index.setTable(table); + index.setTablespace(tableSpace); + index.setName(indexName); + index.setUnique(!nonUnique); + index.setFilterCondition(filterCondition); + indexMap.put(indexName, index); + } + + for (int i = index.getColumns().size(); i < position; i++) { + index.getColumns().add(null); + } + index.getColumns().set(position - 1, columnName); + } + } finally { + JdbcUtils.closeResultSet(rs); + JdbcUtils.closeStatement(statement); + } + + for (Map.Entry entry : indexMap.entrySet()) { + snapshot.addDatabaseObjects(entry.getValue()); + } + + /* + * marks indexes as "associated with" instead of "remove it" + * Index should have associations with: + * foreignKey, primaryKey or uniqueConstraint + * */ + for (Index index : snapshot.getDatabaseObjects(schema, Index.class)) { + for (PrimaryKey pk : snapshot.getDatabaseObjects(schema, PrimaryKey.class)) { + if (index.getTable().getName().equalsIgnoreCase(pk.getTable().getName()) && index.getColumnNames().equals(pk.getColumnNames())) { + index.addAssociatedWith(Index.MARK_PRIMARY_KEY); + } + } + for (ForeignKey fk : snapshot.getDatabaseObjects(schema, ForeignKey.class)) { + if (index.getTable().getName().equalsIgnoreCase(fk.getForeignKeyTable().getName()) && index.getColumnNames().equals(fk.getForeignKeyColumns())) { + index.addAssociatedWith(Index.MARK_FOREIGN_KEY); + } + } + for (UniqueConstraint uc : snapshot.getDatabaseObjects(schema, UniqueConstraint.class)) { + if (index.getTable().getName().equalsIgnoreCase(uc.getTable().getName()) && index.getColumnNames().equals(uc.getColumnNames())) { + index.addAssociatedWith(Index.MARK_UNIQUE_CONSTRAINT); + } + } + } + } // // @Override // protected void readPrimaryKeys(DatabaseSnapshot snapshot, String schema, DatabaseMetaData databaseMetaData) throws DatabaseException, SQLException { From d3c590b28126e407d80f974552b2635931d4ecac Mon Sep 17 00:00:00 2001 From: "nathan.voxland" Date: Sun, 19 Aug 2012 02:01:36 -0500 Subject: [PATCH 03/11] Adding case sensitivity information to Database class --- .../DropAllForeignKeyConstraintsChange.java | 2 +- .../liquibase/database/AbstractDatabase.java | 29 ++++++++++++++++--- .../java/liquibase/database/Database.java | 4 +++ .../diff/output/DiffToChangeLog.java | 2 +- .../liquibase/snapshot/DatabaseSnapshot.java | 4 +-- .../jvm/DerbyDatabaseSnapshotGenerator.java | 4 +-- .../jvm/JdbcDatabaseSnapshotGenerator.java | 28 +++++++++++------- .../jvm/OracleDatabaseSnapshotGenerator.java | 8 ++--- .../liquibase/database/core/MockDatabase.java | 9 ++++++ 9 files changed, 65 insertions(+), 25 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/change/core/DropAllForeignKeyConstraintsChange.java b/liquibase-core/src/main/java/liquibase/change/core/DropAllForeignKeyConstraintsChange.java index 643bcacc531..42f04ef2c23 100644 --- a/liquibase-core/src/main/java/liquibase/change/core/DropAllForeignKeyConstraintsChange.java +++ b/liquibase-core/src/main/java/liquibase/change/core/DropAllForeignKeyConstraintsChange.java @@ -94,7 +94,7 @@ private void generateChildren(Database database) { (String) result.get(FindForeignKeyConstraintsStatement.RESULT_COLUMN_BASE_TABLE_NAME); String constraintName = (String) result.get(FindForeignKeyConstraintsStatement.RESULT_COLUMN_CONSTRAINT_NAME); - if (getBaseTableName().equalsIgnoreCase(baseTableName)) { + if (database.objectNamesEqual(getBaseTableName(), baseTableName)) { if( !handledConstraints.contains(constraintName)) { DropForeignKeyConstraintChange dropForeignKeyConstraintChange = new DropForeignKeyConstraintChange(); diff --git a/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java b/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java index d35c5c4a60f..a555e136b4e 100644 --- a/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java @@ -31,6 +31,7 @@ import java.io.Writer; import java.math.BigInteger; import java.sql.ResultSet; +import java.sql.SQLException; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; @@ -683,6 +684,26 @@ public void checkDatabaseChangeLogLockTable() throws DatabaseException { } } + public boolean isCaseSensitive() { + if (connection != null) { + try { + return !((JdbcConnection) connection).getUnderlyingConnection().getMetaData().supportsMixedCaseIdentifiers(); + } catch (SQLException e) { + LogFactory.getLogger().warning("Cannot determine case sensitivity from JDBC driver", e); + return false; + } + } + return false; + } + + public boolean objectNamesEqual(String name1, String name2) { + if (isCaseSensitive()) { + return name1.equals(name2); + } else { + return name1.equalsIgnoreCase(name2); + } + } + public boolean isReservedWord(String string) { return false; } @@ -788,9 +809,9 @@ public boolean supportsDropTableCascadeConstraints() { public boolean isSystemTable(Schema schema, String tableName) { schema = correctSchema(schema); - if ("information_schema".equalsIgnoreCase(schema.getName())) { + if (this.objectNamesEqual("information_schema", schema.getName())) { return true; - } else if (tableName.equalsIgnoreCase(getDatabaseChangeLogLockTableName())) { + } else if (this.objectNamesEqual(tableName, getDatabaseChangeLogLockTableName())) { return true; } else if (getSystemTablesAndViews().contains(tableName)) { return true; @@ -800,7 +821,7 @@ public boolean isSystemTable(Schema schema, String tableName) { public boolean isSystemView(Schema schema, String viewName) { schema = correctSchema(schema); - if ("information_schema".equalsIgnoreCase(schema.getName())) { + if (this.objectNamesEqual("information_schema", schema.getName())) { return true; } else if (getSystemTablesAndViews().contains(viewName)) { return true; @@ -809,7 +830,7 @@ public boolean isSystemView(Schema schema, String viewName) { } public boolean isLiquibaseTable(String tableName) { - return tableName.equalsIgnoreCase(this.getDatabaseChangeLogTableName()) || tableName.equalsIgnoreCase(this.getDatabaseChangeLogLockTableName()); + return this.objectNamesEqual(tableName, this.getDatabaseChangeLogTableName()) || this.objectNamesEqual(tableName, this.getDatabaseChangeLogLockTableName()); } // ------- DATABASE TAGGING METHODS ---- // diff --git a/liquibase-core/src/main/java/liquibase/database/Database.java b/liquibase-core/src/main/java/liquibase/database/Database.java index 5fee6311524..3ef98cf3e34 100644 --- a/liquibase-core/src/main/java/liquibase/database/Database.java +++ b/liquibase-core/src/main/java/liquibase/database/Database.java @@ -270,6 +270,10 @@ public interface Database extends DatabaseObject, PrioritizedService { void enableForeignKeyChecks() throws DatabaseException; + public boolean isCaseSensitive(); + + public boolean objectNamesEqual(String name1, String name2); + public boolean isReservedWord(String string); Schema correctSchema(Schema schema); diff --git a/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java index 3b2974d1f4a..43b5c32ad13 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java @@ -636,7 +636,7 @@ protected void addMissingTableChanges(List changes) { if (column.isPrimaryKey()) { PrimaryKey primaryKey = null; for (PrimaryKey pk : diffResult.getObjectDiff(PrimaryKey.class).getMissing()) { - if (pk.getTable().getName().equalsIgnoreCase(missingTable.getName())) { + if (diffResult.getComparisonSnapshot().getDatabase().objectNamesEqual(pk.getTable().getName(), missingTable.getName())) { primaryKey = pk; } } diff --git a/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java b/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java index fe13f1d0693..36cb490b24f 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java @@ -52,7 +52,7 @@ public T getDatabaseObject(Schema schema, String obje schema = database.correctSchema(schema); for (DatabaseObject object : getDatabaseObjects(schema, type)) { - if (object.getName().equals(objectName)) { + if (database.objectNamesEqual(object.getName(), objectName)) { //noinspection unchecked return (T) object; } @@ -117,7 +117,7 @@ public boolean isPrimaryKey(Column column) { if (column.getRelation() == null) { continue; } - if (pk.getTable().getName().equalsIgnoreCase(column.getRelation().getName())) { + if (database.objectNamesEqual(pk.getTable().getName(), column.getRelation().getName())) { if (pk.getColumnNamesAsList().contains(column.getName())) { return true; } diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/DerbyDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/DerbyDatabaseSnapshotGenerator.java index b155bba05f0..8aa180b6dd3 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/DerbyDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/DerbyDatabaseSnapshotGenerator.java @@ -25,11 +25,11 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin try { ResultSet rs = getMetaData(database).getIndexInfo(schema.getCatalogName(), schema.getName(), "%", false, true); while (rs.next()) { - if (rs.getString("INDEX_NAME").equalsIgnoreCase(indexName)) { + if (database.objectNamesEqual(rs.getString("INDEX_NAME"), indexName)) { return true; } if (tableName != null && columnNames != null) { - if (tableName.equalsIgnoreCase(rs.getString("TABLE_NAME")) && columnNames.replaceAll(" ","").equalsIgnoreCase(rs.getString("COLUMN_NAME").replaceAll(" ",""))) { + if (database.objectNamesEqual(tableName, rs.getString("TABLE_NAME")) && database.objectNamesEqual(columnNames.replaceAll(" ",""), rs.getString("COLUMN_NAME").replaceAll(" ",""))) { return true; } } diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java index c2390ce0327..3381fd4a658 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java @@ -49,8 +49,14 @@ public boolean hasDatabaseChangeLogLockTable(Database database) { } public boolean hasTable(Schema schema, String tableName, Database database) { + if (schema == null) { + schema = Schema.DEFAULT; + } try { - ResultSet rs = getMetaData(database).getTables(schema.getCatalogName(), schema.getName(), database.correctTableName(tableName), new String[]{"TABLE"}); + if (database != null) { + tableName = database.correctTableName(tableName); + } + ResultSet rs = getMetaData(database).getTables(schema.getCatalogName(), schema.getName(), tableName, new String[]{"TABLE"}); try { return rs.next(); } finally { @@ -349,12 +355,12 @@ protected void readTables(DatabaseSnapshot snapshot, Schema schema, DatabaseMeta while (tableMetaDataRs.next()) { Table table = readTable(tableMetaDataRs, database, false); if (database.isLiquibaseTable(table.getName())) { - if (table.getName().equals(database.getDatabaseChangeLogTableName())) { + if (database.objectNamesEqual(table.getName(), database.getDatabaseChangeLogTableName())) { snapshot.setDatabaseChangeLogTable(table); continue; } - if (table.getName().equals(database.getDatabaseChangeLogLockTableName())) { + if (database.objectNamesEqual(table.getName(), database.getDatabaseChangeLogLockTableName())) { snapshot.setDatabaseChangeLogLockTable(table); continue; } @@ -670,7 +676,7 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin try { while (rs.next()) { String foundIndexName = rs.getString("INDEX_NAME"); - if (indexName != null && !foundIndexName.equals(indexName)) { + if (indexName != null && !database.objectNamesEqual(foundIndexName, indexName)) { continue; } short ordinalPosition = rs.getShort("ORDINAL_POSITION"); @@ -685,7 +691,7 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin for (TreeMap columnList : columnsByIndexName.values()) { - if (StringUtils.join(columnList.values(), ",").equals(columnNames)) { + if (database.objectNamesEqual(StringUtils.join(columnList.values(), ","), columnNames)) { return true; } } @@ -697,7 +703,7 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin ResultSet rs = getMetaData(database).getIndexInfo(schema.getCatalogName(), schema.getName(), database.correctTableName(tableName), false, true); try { while (rs.next()) { - if (rs.getString("INDEX_NAME").equals(database.correctIndexName(indexName))) { + if (database.objectNamesEqual(rs.getString("INDEX_NAME"), database.correctIndexName(indexName))) { return true; } } @@ -721,7 +727,7 @@ public boolean hasForeignKey(Schema schema, String foreignKeyTableName, String f ResultSet rs = getMetaData(database).getImportedKeys(schema.getCatalogName(), schema.getName(), database.correctTableName(foreignKeyTableName)); try { while (rs.next()) { - if (rs.getString("FK_NAME").equals(database.correctForeignKeyName(fkName))) { + if (database.objectNamesEqual(rs.getString("FK_NAME"), database.correctForeignKeyName(fkName))) { return true; } } @@ -925,17 +931,17 @@ protected void readIndexes(DatabaseSnapshot snapshot, Schema schema, DatabaseMet * */ for (Index index : snapshot.getDatabaseObjects(schema, Index.class)) { for (PrimaryKey pk : snapshot.getDatabaseObjects(schema, PrimaryKey.class)) { - if (index.getTable().getName().equalsIgnoreCase(pk.getTable().getName()) && index.getColumnNames().equals(pk.getColumnNames())) { + if (database.objectNamesEqual(index.getTable().getName(), pk.getTable().getName()) && database.objectNamesEqual(index.getColumnNames(), pk.getColumnNames())) { index.addAssociatedWith(Index.MARK_PRIMARY_KEY); } } for (ForeignKey fk : snapshot.getDatabaseObjects(schema, ForeignKey.class)) { - if (index.getTable().getName().equalsIgnoreCase(fk.getForeignKeyTable().getName()) && index.getColumnNames().equals(fk.getForeignKeyColumns())) { + if (database.objectNamesEqual(index.getTable().getName(), fk.getForeignKeyTable().getName()) && database.objectNamesEqual(index.getColumnNames(), fk.getForeignKeyColumns())) { index.addAssociatedWith(Index.MARK_FOREIGN_KEY); } } for (UniqueConstraint uc : snapshot.getDatabaseObjects(schema, UniqueConstraint.class)) { - if (index.getTable().getName().equalsIgnoreCase(uc.getTable().getName()) && index.getColumnNames().equals(uc.getColumnNames())) { + if (database.objectNamesEqual(index.getTable().getName(), uc.getTable().getName()) && database.objectNamesEqual(index.getColumnNames(), uc.getColumnNames())) { index.addAssociatedWith(Index.MARK_UNIQUE_CONSTRAINT); } } @@ -970,7 +976,7 @@ protected void readPrimaryKeys(DatabaseSnapshot snapshot, Schema schema, Databas boolean foundExistingPK = false; for (PrimaryKey pk : foundPKs) { - if (pk.getTable().getName().equals(tableName)) { + if (database.objectNamesEqual(pk.getTable().getName(), tableName)) { pk.addColumnName(position - 1, columnName); foundExistingPK = true; diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java index 383dfe6429b..6ccf00bc3f5 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java @@ -365,17 +365,17 @@ protected void readIndexes(DatabaseSnapshot snapshot, Schema schema, DatabaseMet * */ for (Index index : snapshot.getDatabaseObjects(schema, Index.class)) { for (PrimaryKey pk : snapshot.getDatabaseObjects(schema, PrimaryKey.class)) { - if (index.getTable().getName().equalsIgnoreCase(pk.getTable().getName()) && index.getColumnNames().equals(pk.getColumnNames())) { + if (database.objectNamesEqual(index.getTable().getName(), pk.getTable().getName()) && database.objectNamesEqual(index.getColumnNames(), pk.getColumnNames())) { index.addAssociatedWith(Index.MARK_PRIMARY_KEY); } } for (ForeignKey fk : snapshot.getDatabaseObjects(schema, ForeignKey.class)) { - if (index.getTable().getName().equalsIgnoreCase(fk.getForeignKeyTable().getName()) && index.getColumnNames().equals(fk.getForeignKeyColumns())) { + if (database.objectNamesEqual(index.getTable().getName(), fk.getForeignKeyTable().getName()) && database.objectNamesEqual(index.getColumnNames(), fk.getForeignKeyColumns())) { index.addAssociatedWith(Index.MARK_FOREIGN_KEY); } } for (UniqueConstraint uc : snapshot.getDatabaseObjects(schema, UniqueConstraint.class)) { - if (index.getTable().getName().equalsIgnoreCase(uc.getTable().getName()) && index.getColumnNames().equals(uc.getColumnNames())) { + if (database.objectNamesEqual(index.getTable().getName(), uc.getTable().getName()) && database.objectNamesEqual(index.getColumnNames(), uc.getColumnNames())) { index.addAssociatedWith(Index.MARK_UNIQUE_CONSTRAINT); } } @@ -408,7 +408,7 @@ protected void readIndexes(DatabaseSnapshot snapshot, Schema schema, DatabaseMet // // boolean foundExistingPK = false; // for (PrimaryKey pk : foundPKs) { -// if (pk.getTable().getName().equals(tableName)) { +// if (database.objectNamesEqual(pk.getTable().getName(), tableName)) { // pk.addColumnName(position - 1, columnName); // // foundExistingPK = true; diff --git a/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java b/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java index 247db70a0c6..9feb9e8bb77 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java +++ b/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java @@ -88,6 +88,15 @@ public boolean isAutoCommit() throws DatabaseException { return false; } + + public boolean isCaseSensitive() { + return false; + } + + public boolean objectNamesEqual(String name1, String name2) { + return name1.equalsIgnoreCase(name2); + } + public void setAutoCommit(boolean b) throws DatabaseException { } From ce633955176850f928d35067b7f91a3f1b3c4f57 Mon Sep 17 00:00:00 2001 From: "nathan.voxland" Date: Mon, 20 Aug 2012 01:40:14 -0500 Subject: [PATCH 04/11] working on DB2 failing integration tests. Still not working --- .../liquibase/database/AbstractDatabase.java | 6 ++++ .../liquibase/database/core/DB2Database.java | 10 +++--- .../liquibase/datatype/core/BooleanType.java | 33 +++++++++++++++---- .../liquibase/datatype/core/NumericType.java | 3 +- .../jvm/JdbcDatabaseSnapshotGenerator.java | 2 ++ 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java b/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java index a555e136b4e..af8a429926f 100644 --- a/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java @@ -697,6 +697,12 @@ public boolean isCaseSensitive() { } public boolean objectNamesEqual(String name1, String name2) { + if (name1 == null && name2 == null) { + return true; + } + if (name1 == null || name2 == null) { + return false; + } if (isCaseSensitive()) { return name1.equals(name2); } else { diff --git a/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java b/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java index ee51cedbff1..7dbc443531a 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java +++ b/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java @@ -37,6 +37,11 @@ public Integer getDefaultPort() { return 446; } + @Override + public boolean supportsSchemas() { + return false; + } + @Override protected String getDefaultDatabaseProductName() { return "DB2"; @@ -73,11 +78,6 @@ public String getDefaultSchemaName() { return defaultSchemaName; } - @Override - public Schema correctSchema(Schema schema) { - return schema; - } - @Override protected String correctObjectName(String objectName) { return objectName.toUpperCase(); diff --git a/liquibase-core/src/main/java/liquibase/datatype/core/BooleanType.java b/liquibase-core/src/main/java/liquibase/datatype/core/BooleanType.java index 162cc904d87..065cd1745b2 100644 --- a/liquibase-core/src/main/java/liquibase/datatype/core/BooleanType.java +++ b/liquibase-core/src/main/java/liquibase/datatype/core/BooleanType.java @@ -19,12 +19,12 @@ public DatabaseDataType toDatabaseDataType(Database database) { } else if (database instanceof MSSQLDatabase) { return new DatabaseDataType("BIT"); } else if (database instanceof MySQLDatabase) { - return new DatabaseDataType("TINYINT",1); + return new DatabaseDataType("TINYINT", 1); } else if (database instanceof OracleDatabase) { return new DatabaseDataType("NUMBER", 1); - } else if (database instanceof SybaseASADatabase || database instanceof SybaseDatabase) { + } else if (database instanceof SybaseASADatabase || database instanceof SybaseDatabase) { return new DatabaseDataType("BIT"); - } else if (database instanceof DerbyDatabase) { + } else if (database instanceof DerbyDatabase) { return new DatabaseDataType("SMALLINT"); } @@ -61,15 +61,33 @@ public String objectToString(Object value, Database database) { return returnValue; } - //todo: informix 't' and 'f' + protected boolean isNumericBoolean(Database database) { + if (database instanceof CacheDatabase + || database instanceof DB2Database + || database instanceof FirebirdDatabase + || database instanceof MSSQLDatabase + || database instanceof MySQLDatabase + || database instanceof OracleDatabase + || database instanceof SybaseASADatabase + || database instanceof SybaseDatabase + || database instanceof DerbyDatabase) { + return true; + } else { + return false; + } + + } /** * The database-specific value to use for "false" "boolean" columns. */ public String getFalseBooleanValue(Database database) { - if (database instanceof MSSQLDatabase) { + if (isNumericBoolean(database)) { return "0"; } + if (database instanceof InformixDatabase) { + return "f"; + } return "FALSE"; } @@ -77,9 +95,12 @@ public String getFalseBooleanValue(Database database) { * The database-specific value to use for "true" "boolean" columns. */ public String getTrueBooleanValue(Database database) { - if (database instanceof MSSQLDatabase) { + if (isNumericBoolean(database)) { return "1"; } + if (database instanceof InformixDatabase) { + return "t"; + } return "TRUE"; } diff --git a/liquibase-core/src/main/java/liquibase/datatype/core/NumericType.java b/liquibase-core/src/main/java/liquibase/datatype/core/NumericType.java index 29c8ded0ecc..b3389515370 100644 --- a/liquibase-core/src/main/java/liquibase/datatype/core/NumericType.java +++ b/liquibase-core/src/main/java/liquibase/datatype/core/NumericType.java @@ -1,6 +1,7 @@ package liquibase.datatype.core; import liquibase.database.Database; +import liquibase.database.core.DB2Database; import liquibase.database.core.MySQLDatabase; import liquibase.datatype.DataTypeInfo; import liquibase.datatype.DatabaseDataType; @@ -10,7 +11,7 @@ public class NumericType extends LiquibaseDataType { @Override public DatabaseDataType toDatabaseDataType(Database database) { - if (database instanceof MySQLDatabase) { + if (database instanceof MySQLDatabase || database instanceof DB2Database) { return new DatabaseDataType("numeric", getParameters()); } return super.toDatabaseDataType(database); diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java index 3381fd4a658..32598a33862 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java @@ -55,6 +55,7 @@ public boolean hasTable(Schema schema, String tableName, Database database) { try { if (database != null) { tableName = database.correctTableName(tableName); + schema = database.correctSchema(schema); } ResultSet rs = getMetaData(database).getTables(schema.getCatalogName(), schema.getName(), tableName, new String[]{"TABLE"}); try { @@ -347,6 +348,7 @@ protected DatabaseMetaData getMetaData(Database database) throws SQLException { protected void readTables(DatabaseSnapshot snapshot, Schema schema, DatabaseMetaData databaseMetaData) throws SQLException, DatabaseException { + schema = snapshot.getDatabase().correctSchema(schema); Database database = snapshot.getDatabase(); updateListeners("Reading tables for " + database.toString() + " ..."); From 7f0f085caa81fc33a4579175776b7a478b856522 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Tue, 21 Aug 2012 19:19:56 +0200 Subject: [PATCH 05/11] git-ignoring .classpath --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 4139265c517..050e869af64 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ target .project .settings +.classpath liquibase.iws -out \ No newline at end of file +out From 988d5d4114ae388c18ded23921cee18db8303d82 Mon Sep 17 00:00:00 2001 From: Vincent Ricard Date: Tue, 21 Aug 2012 21:18:34 +0200 Subject: [PATCH 06/11] fixing CORE-916 by making the change log file required for the 'status' command --- .../src/main/java/liquibase/integration/commandline/Main.java | 1 + 1 file changed, 1 insertion(+) diff --git a/liquibase-core/src/main/java/liquibase/integration/commandline/Main.java b/liquibase-core/src/main/java/liquibase/integration/commandline/Main.java index 71c83dd33c6..deddb5367b5 100644 --- a/liquibase-core/src/main/java/liquibase/integration/commandline/Main.java +++ b/liquibase-core/src/main/java/liquibase/integration/commandline/Main.java @@ -304,6 +304,7 @@ private boolean isChangeLogRequired(String command) { return command.toLowerCase().startsWith("update") || command.toLowerCase().startsWith("rollback") || "calculateCheckSum".equalsIgnoreCase(command) + || "status".equalsIgnoreCase(command) || "validate".equalsIgnoreCase(command) || "changeLogSync".equalsIgnoreCase(command) || "changeLogSyncSql".equalsIgnoreCase(command); From 06dbf42ac6787a713d8679892dfca5dc9ce655bf Mon Sep 17 00:00:00 2001 From: "nathan.voxland" Date: Wed, 22 Aug 2012 01:39:28 -0500 Subject: [PATCH 07/11] Moving around how the "is this the same object" logic is stored for better case sensitivity support --- .../DropAllForeignKeyConstraintsChange.java | 3 +- .../liquibase/change/core/LoadDataChange.java | 2 +- .../liquibase/database/AbstractDatabase.java | 59 +++++++++-------- .../java/liquibase/database/Database.java | 4 +- .../database/core/InformixDatabase.java | 2 +- .../database/core/MSSQLDatabase.java | 2 +- .../database/core/MaxDBDatabase.java | 2 +- .../database/core/PostgresDatabase.java | 3 +- .../database/core/SQLiteDatabase.java | 2 +- .../database/core/SybaseASADatabase.java | 2 +- .../database/core/SybaseDatabase.java | 3 +- .../liquibase/database/structure/Column.java | 2 +- .../database/structure/DatabaseObject.java | 9 ++- .../structure/DatabaseObjectImpl.java | 21 +++++++ .../database/structure/ForeignKey.java | 35 +++++++---- .../liquibase/database/structure/Index.java | 48 +++++++++++--- .../database/structure/PrimaryKey.java | 2 +- .../database/structure/Relation.java | 2 +- .../liquibase/database/structure/Schema.java | 2 +- .../database/structure/Sequence.java | 2 +- .../database/structure/UniqueConstraint.java | 2 +- .../diff/core/StandardDiffGenerator.java | 8 +-- .../diff/output/DiffToChangeLog.java | 9 ++- .../liquibase/snapshot/DatabaseSnapshot.java | 4 +- .../jvm/DerbyDatabaseSnapshotGenerator.java | 44 ++++++------- .../jvm/JdbcDatabaseSnapshotGenerator.java | 63 ++++++++++++------- .../jvm/OracleDatabaseSnapshotGenerator.java | 10 +-- .../PostgresDatabaseSnapshotGenerator.java | 2 +- .../liquibase/database/core/MockDatabase.java | 14 +++-- .../dbtest/AbstractIntegrationTest.java | 2 +- 30 files changed, 226 insertions(+), 139 deletions(-) create mode 100644 liquibase-core/src/main/java/liquibase/database/structure/DatabaseObjectImpl.java diff --git a/liquibase-core/src/main/java/liquibase/change/core/DropAllForeignKeyConstraintsChange.java b/liquibase-core/src/main/java/liquibase/change/core/DropAllForeignKeyConstraintsChange.java index 42f04ef2c23..4831ac27e5d 100644 --- a/liquibase-core/src/main/java/liquibase/change/core/DropAllForeignKeyConstraintsChange.java +++ b/liquibase-core/src/main/java/liquibase/change/core/DropAllForeignKeyConstraintsChange.java @@ -5,6 +5,7 @@ import liquibase.change.ChangeMetaData; import liquibase.change.ChangeProperty; import liquibase.database.Database; +import liquibase.database.structure.Table; import liquibase.exception.DatabaseException; import liquibase.exception.UnexpectedLiquibaseException; import liquibase.executor.Executor; @@ -94,7 +95,7 @@ private void generateChildren(Database database) { (String) result.get(FindForeignKeyConstraintsStatement.RESULT_COLUMN_BASE_TABLE_NAME); String constraintName = (String) result.get(FindForeignKeyConstraintsStatement.RESULT_COLUMN_CONSTRAINT_NAME); - if (database.objectNamesEqual(getBaseTableName(), baseTableName)) { + if (new Table(getBaseTableName()).equals(new Table(baseTableName), database)) { if( !handledConstraints.contains(constraintName)) { DropForeignKeyConstraintChange dropForeignKeyConstraintChange = new DropForeignKeyConstraintChange(); diff --git a/liquibase-core/src/main/java/liquibase/change/core/LoadDataChange.java b/liquibase-core/src/main/java/liquibase/change/core/LoadDataChange.java index 4fbe14e5615..cc553c3c5b8 100644 --- a/liquibase-core/src/main/java/liquibase/change/core/LoadDataChange.java +++ b/liquibase-core/src/main/java/liquibase/change/core/LoadDataChange.java @@ -133,7 +133,7 @@ public SqlStatement[] generateStatements(Database database) { if (columnConfig != null) { columnName = columnConfig.getName(); - if (columnConfig.getType().equalsIgnoreCase("SKIP")) { + if ("skip".equalsIgnoreCase(columnConfig.getType())) { continue; } diff --git a/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java b/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java index af8a429926f..1bb5d40a8b5 100644 --- a/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java @@ -284,9 +284,17 @@ public void setDefaultSchemaName(String schemaName) { } /** - * Returns system (undroppable) tables and views. + * Returns system (undroppable) views. */ - protected Set getSystemTablesAndViews() { + protected Set getSystemTables() { + return new HashSet(); + } + + + /** + * Returns system (undroppable) views. + */ + protected Set getSystemViews() { return new HashSet(); } @@ -687,7 +695,7 @@ public void checkDatabaseChangeLogLockTable() throws DatabaseException { public boolean isCaseSensitive() { if (connection != null) { try { - return !((JdbcConnection) connection).getUnderlyingConnection().getMetaData().supportsMixedCaseIdentifiers(); + return ((JdbcConnection) connection).getUnderlyingConnection().getMetaData().supportsMixedCaseIdentifiers(); } catch (SQLException e) { LogFactory.getLogger().warning("Cannot determine case sensitivity from JDBC driver", e); return false; @@ -696,20 +704,6 @@ public boolean isCaseSensitive() { return false; } - public boolean objectNamesEqual(String name1, String name2) { - if (name1 == null && name2 == null) { - return true; - } - if (name1 == null || name2 == null) { - return false; - } - if (isCaseSensitive()) { - return name1.equals(name2); - } else { - return name1.equalsIgnoreCase(name2); - } - } - public boolean isReservedWord(String string) { return false; } @@ -815,31 +809,28 @@ public boolean supportsDropTableCascadeConstraints() { public boolean isSystemTable(Schema schema, String tableName) { schema = correctSchema(schema); - if (this.objectNamesEqual("information_schema", schema.getName())) { - return true; - } else if (this.objectNamesEqual(tableName, getDatabaseChangeLogLockTableName())) { - return true; - } else if (getSystemTablesAndViews().contains(tableName)) { - return true; - } - return false; + return "information_schema".equalsIgnoreCase(schema.getName()) || getSystemTables().contains(tableName); } public boolean isSystemView(Schema schema, String viewName) { schema = correctSchema(schema); - if (this.objectNamesEqual("information_schema", schema.getName())) { + if ("information_schema".equalsIgnoreCase(schema.getName())) { return true; - } else if (getSystemTablesAndViews().contains(viewName)) { + } else if (getSystemViews().contains(viewName)) { return true; } return false; } - public boolean isLiquibaseTable(String tableName) { - return this.objectNamesEqual(tableName, this.getDatabaseChangeLogTableName()) || this.objectNamesEqual(tableName, this.getDatabaseChangeLogLockTableName()); + public boolean isLiquibaseTable(Schema schema, String tableName) { + if (isCaseSensitive()) { + return tableName.equals(this.getDatabaseChangeLogTableName()) || tableName.equals(this.getDatabaseChangeLogLockTableName()); + } else { + return tableName.equalsIgnoreCase(this.getDatabaseChangeLogTableName()) || tableName.equalsIgnoreCase(this.getDatabaseChangeLogLockTableName()); + } } -// ------- DATABASE TAGGING METHODS ---- // + // ------- DATABASE TAGGING METHODS ---- // /** * Tags the database changelog with the given string. @@ -1278,4 +1269,12 @@ public boolean disableForeignKeyChecks() throws DatabaseException { public void enableForeignKeyChecks() throws DatabaseException { throw new DatabaseException("ForeignKeyChecks Management not supported"); } + + public boolean equals(DatabaseObject otherObject, Database accordingTo) { + return otherObject.getClass().equals(this.getClass()); + } + + public boolean equals(String otherObject, Database accordingTo) { + return this.getName().equals(otherObject); + } } diff --git a/liquibase-core/src/main/java/liquibase/database/Database.java b/liquibase-core/src/main/java/liquibase/database/Database.java index 3ef98cf3e34..bfe5791de74 100644 --- a/liquibase-core/src/main/java/liquibase/database/Database.java +++ b/liquibase-core/src/main/java/liquibase/database/Database.java @@ -146,7 +146,7 @@ public interface Database extends DatabaseObject, PrioritizedService { boolean isSystemTable(Schema schema, String tableName); - boolean isLiquibaseTable(String tableName); + boolean isLiquibaseTable(Schema schema, String tableName); boolean shouldQuoteValue(String value); @@ -272,8 +272,6 @@ public interface Database extends DatabaseObject, PrioritizedService { public boolean isCaseSensitive(); - public boolean objectNamesEqual(String name1, String name2); - public boolean isReservedWord(String string); Schema correctSchema(Schema schema); diff --git a/liquibase-core/src/main/java/liquibase/database/core/InformixDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/InformixDatabase.java index 4f89358f356..cc2dd8c849a 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/InformixDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/InformixDatabase.java @@ -95,7 +95,7 @@ public InformixDatabase() { } @Override - protected Set getSystemTablesAndViews() { + protected Set getSystemViews() { return systemTablesAndViews; } diff --git a/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java index 25475fbd0bc..4c855952fe9 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java @@ -71,7 +71,7 @@ public Integer getDefaultPort() { } @Override - public Set getSystemTablesAndViews() { + public Set getSystemViews() { return systemTablesAndViews; } diff --git a/liquibase-core/src/main/java/liquibase/database/core/MaxDBDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/MaxDBDatabase.java index 3da6728b72c..cf937c72ac0 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/MaxDBDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/MaxDBDatabase.java @@ -87,7 +87,7 @@ public int getPriority() { } @Override - public Set getSystemTablesAndViews() { + public Set getSystemViews() { return systemTablesAndViews; } diff --git a/liquibase-core/src/main/java/liquibase/database/core/PostgresDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/PostgresDatabase.java index f83af22015e..c9ca3120c97 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/PostgresDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/PostgresDatabase.java @@ -10,7 +10,6 @@ import liquibase.statement.core.RawSqlStatement; import java.math.BigInteger; -import java.sql.SQLException; import java.util.*; /** @@ -102,7 +101,7 @@ public Integer getDefaultPort() { } @Override - public Set getSystemTablesAndViews() { + public Set getSystemViews() { return systemTablesAndViews; } diff --git a/liquibase-core/src/main/java/liquibase/database/core/SQLiteDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/SQLiteDatabase.java index 75df1402df8..3c5361444ca 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/SQLiteDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/SQLiteDatabase.java @@ -190,7 +190,7 @@ public static List getAlterTableStatements( } @Override - protected Set getSystemTablesAndViews() { + protected Set getSystemViews() { return systemTables; } diff --git a/liquibase-core/src/main/java/liquibase/database/core/SybaseASADatabase.java b/liquibase-core/src/main/java/liquibase/database/core/SybaseASADatabase.java index 0eef66598a3..a064018299f 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/SybaseASADatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/SybaseASADatabase.java @@ -214,7 +214,7 @@ public boolean supportsTablespaces() { } @Override - public Set getSystemTablesAndViews() { + public Set getSystemViews() { return systemTablesAndViews; } diff --git a/liquibase-core/src/main/java/liquibase/database/core/SybaseDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/SybaseDatabase.java index b96b167053d..d2fe6f9208b 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/SybaseDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/SybaseDatabase.java @@ -4,7 +4,6 @@ import liquibase.database.DatabaseConnection; import liquibase.database.structure.Schema; import liquibase.exception.DatabaseException; -import liquibase.exception.UnexpectedLiquibaseException; import liquibase.executor.Executor; import liquibase.executor.ExecutorService; import liquibase.logging.LogFactory; @@ -84,7 +83,7 @@ public boolean supportsDDLInTransaction() { } @Override - public Set getSystemTablesAndViews() { + public Set getSystemViews() { return systemTablesAndViews; } diff --git a/liquibase-core/src/main/java/liquibase/database/structure/Column.java b/liquibase-core/src/main/java/liquibase/database/structure/Column.java index 4fccb0dc585..d5eb2609247 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/Column.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/Column.java @@ -1,6 +1,6 @@ package liquibase.database.structure; -public class Column implements DatabaseObject, Comparable { +public class Column extends DatabaseObjectImpl implements Comparable { private Relation relation; private String name; private Boolean nullable; diff --git a/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObject.java b/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObject.java index 4a083b3a74e..f091856182d 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObject.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObject.java @@ -1,9 +1,16 @@ package liquibase.database.structure; +import liquibase.database.Database; + public interface DatabaseObject { DatabaseObject[] getContainingObjects(); - public String getName(); + String getName(); Schema getSchema(); + + boolean equals(DatabaseObject otherObject, Database accordingTo); + + boolean equals(String otherObjectName, Database accordingTo); + } diff --git a/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObjectImpl.java b/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObjectImpl.java new file mode 100644 index 00000000000..ebf86fedbb6 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObjectImpl.java @@ -0,0 +1,21 @@ +package liquibase.database.structure; + +import liquibase.database.Database; + +public abstract class DatabaseObjectImpl implements DatabaseObject { + + public boolean equals(DatabaseObject otherObject, Database accordingTo) { + return equals(otherObject.getName(), accordingTo); + } + + public boolean equals(String otherObjectName, Database accordingTo) { + if (otherObjectName == null) { + return false; + } + if (accordingTo.isCaseSensitive()) { + return this.getName().equals(otherObjectName); + } else { + return this.getName().equalsIgnoreCase(otherObjectName); + } + } +} diff --git a/liquibase-core/src/main/java/liquibase/database/structure/ForeignKey.java b/liquibase-core/src/main/java/liquibase/database/structure/ForeignKey.java index 095529d51fa..03a7a090ef7 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/ForeignKey.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/ForeignKey.java @@ -2,7 +2,7 @@ import java.util.List; -public class ForeignKey implements DatabaseObject, Comparable { +public class ForeignKey extends DatabaseObjectImpl implements Comparable { private Table primaryKeyTable; private String primaryKeyColumns; @@ -48,8 +48,9 @@ public Table getPrimaryKeyTable() { return primaryKeyTable; } - public void setPrimaryKeyTable(Table primaryKeyTable) { + public ForeignKey setPrimaryKeyTable(Table primaryKeyTable) { this.primaryKeyTable = primaryKeyTable; + return this; } public String getPrimaryKeyColumns() { @@ -66,16 +67,18 @@ public void addPrimaryKeyColumn(String primaryKeyColumn) { } } - public void setPrimaryKeyColumns(String primaryKeyColumns) { + public ForeignKey setPrimaryKeyColumns(String primaryKeyColumns) { this.primaryKeyColumns = primaryKeyColumns; + return this; } public Table getForeignKeyTable() { return foreignKeyTable; } - public void setForeignKeyTable(Table foreignKeyTable) { + public ForeignKey setForeignKeyTable(Table foreignKeyTable) { this.foreignKeyTable = foreignKeyTable; + return this; } public String getForeignKeyColumns() { @@ -92,16 +95,18 @@ public void addForeignKeyColumn(String foreignKeyColumn) { } } - public void setForeignKeyColumns(String foreignKeyColumns) { + public ForeignKey setForeignKeyColumns(String foreignKeyColumns) { this.foreignKeyColumns = foreignKeyColumns; + return this; } public String getName() { return name; } - public void setName(String name) { + public ForeignKey setName(String name) { this.name = name; + return this; } @@ -115,8 +120,9 @@ public boolean isDeferrable() { return deferrable; } - public void setDeferrable(boolean deferrable) { + public ForeignKey setDeferrable(boolean deferrable) { this.deferrable = deferrable; + return this; } @@ -124,20 +130,23 @@ public boolean isInitiallyDeferred() { return initiallyDeferred; } - public void setInitiallyDeferred(boolean initiallyDeferred) { + public ForeignKey setInitiallyDeferred(boolean initiallyDeferred) { this.initiallyDeferred = initiallyDeferred; + return this; } - public void setUpdateRule(ForeignKeyConstraintType rule) { + public ForeignKey setUpdateRule(ForeignKeyConstraintType rule) { this.updateRule = rule; + return this; } public ForeignKeyConstraintType getUpdateRule() { return this.updateRule; } - public void setDeleteRule(ForeignKeyConstraintType rule) { + public ForeignKey setDeleteRule(ForeignKeyConstraintType rule) { this.deleteRule = rule; + return this; } public ForeignKeyConstraintType getDeleteRule() { @@ -148,8 +157,9 @@ public boolean getReferencesUniqueColumn() { return referencesUniqueColumn; } - public void setReferencesUniqueColumn(boolean referencesUniqueColumn) { + public ForeignKey setReferencesUniqueColumn(boolean referencesUniqueColumn) { this.referencesUniqueColumn = referencesUniqueColumn; + return this; } @Override @@ -234,7 +244,8 @@ public Index getBackingIndex() { return backingIndex; } - public void setBackingIndex(Index backingIndex) { + public ForeignKey setBackingIndex(Index backingIndex) { this.backingIndex = backingIndex; + return this; } } diff --git a/liquibase-core/src/main/java/liquibase/database/structure/Index.java b/liquibase-core/src/main/java/liquibase/database/structure/Index.java index 34c97e4fae4..2555c0d6498 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/Index.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/Index.java @@ -1,10 +1,12 @@ package liquibase.database.structure; +import liquibase.database.Database; +import liquibase.exception.UnexpectedLiquibaseException; import liquibase.util.StringUtils; import java.util.*; -public class Index implements DatabaseObject, Comparable { +public class Index extends DatabaseObjectImpl implements Comparable { /** Marks Index as associated with Primary Key [PK] */ public final static String MARK_PRIMARY_KEY = "primaryKey"; @@ -33,8 +35,9 @@ public String getName() { return name; } - public void setName(String name) { + public Index setName(String name) { this.name = name; + return this; } public Schema getSchema() { @@ -49,16 +52,18 @@ public Table getTable() { return table; } - public void setTable(Table table) { + public Index setTable(Table table) { this.table = table; + return this; } public String getTablespace() { return tablespace; } - public void setTablespace(String tablespace) { + public Index setTablespace(String tablespace) { this.tablespace = tablespace; + return this; } public List getColumns() { @@ -73,12 +78,14 @@ public String getFilterCondition() { return filterCondition; } - public void setFilterCondition(String filterCondition) { + public Index setFilterCondition(String filterCondition) { this.filterCondition = filterCondition; + return this; } - public void setUnique(Boolean value) { + public Index setUnique(Boolean value) { this.unique = value; + return this; } public Boolean isUnique() { @@ -101,7 +108,34 @@ public boolean isAssociatedWith(String keyword) { return associatedWith.contains(keyword); } - @Override + @Override + public boolean equals(DatabaseObject otherObject, Database accordingTo) { + if (!(otherObject instanceof Index)) { + return false; + } + Index otherIndex = (Index) otherObject; + + if (((Index) otherObject).getColumns().size() == 0) { + return super.equals(otherObject, accordingTo); //fall back to name + } + + if (this.getTable() != null) { + return this.getTable().equals(((Index) otherObject).getTable(), accordingTo); + } + + if (otherIndex.getColumns() != null & otherIndex.getColumns().size() > 0) { + for (int i=0; i { +public class PrimaryKey extends DatabaseObjectImpl implements Comparable { private String name; private List columnNames = new ArrayList(); private Table table; diff --git a/liquibase-core/src/main/java/liquibase/database/structure/Relation.java b/liquibase-core/src/main/java/liquibase/database/structure/Relation.java index 3d9da315de7..fe37478c3c7 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/Relation.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/Relation.java @@ -8,7 +8,7 @@ /** * A container of columns. Usually a table or view. */ -public abstract class Relation implements DatabaseObject, Comparable { +public abstract class Relation extends DatabaseObjectImpl implements Comparable { private Database database; private Schema schema; protected String name; diff --git a/liquibase-core/src/main/java/liquibase/database/structure/Schema.java b/liquibase-core/src/main/java/liquibase/database/structure/Schema.java index b84dd74f845..a608e2956cb 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/Schema.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/Schema.java @@ -2,7 +2,7 @@ import liquibase.util.StringUtils; -public class Schema implements DatabaseObject { +public class Schema extends DatabaseObjectImpl { public static final String DEFAULT_NAME = "!DEFAULT_SCHEMA!"; public static final Schema DEFAULT = new Schema(Catalog.DEFAULT, DEFAULT_NAME); diff --git a/liquibase-core/src/main/java/liquibase/database/structure/Sequence.java b/liquibase-core/src/main/java/liquibase/database/structure/Sequence.java index 23f06afb65d..07933f2a4ca 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/Sequence.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/Sequence.java @@ -1,6 +1,6 @@ package liquibase.database.structure; -public class Sequence implements DatabaseObject, Comparable { +public class Sequence extends DatabaseObjectImpl implements Comparable { private String name; private Schema schema; diff --git a/liquibase-core/src/main/java/liquibase/database/structure/UniqueConstraint.java b/liquibase-core/src/main/java/liquibase/database/structure/UniqueConstraint.java index 076651e2508..72862e71bdf 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/UniqueConstraint.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/UniqueConstraint.java @@ -5,7 +5,7 @@ import java.util.ArrayList; import java.util.List; -public class UniqueConstraint implements DatabaseObject, Comparable { +public class UniqueConstraint extends DatabaseObjectImpl implements Comparable { private String name; private Table table; private List columns = new ArrayList(); diff --git a/liquibase-core/src/main/java/liquibase/diff/core/StandardDiffGenerator.java b/liquibase-core/src/main/java/liquibase/diff/core/StandardDiffGenerator.java index e84df069aeb..75c8d02ee92 100644 --- a/liquibase-core/src/main/java/liquibase/diff/core/StandardDiffGenerator.java +++ b/liquibase-core/src/main/java/liquibase/diff/core/StandardDiffGenerator.java @@ -10,10 +10,6 @@ import liquibase.snapshot.DatabaseSnapshot; import liquibase.snapshot.DatabaseSnapshotGeneratorFactory; -import java.util.HashSet; -import java.util.List; -import java.util.Set; - public class StandardDiffGenerator implements DiffGenerator { public int getPriority() { @@ -75,7 +71,7 @@ protected void compareObjectType(Class type, Datab comparisonSchema = comparisonSnapshot.getDatabase().correctSchema(schemaComparison.getComparisonSchema()); } for (T referenceObject : referenceSnapshot.getDatabaseObjects(referenceSchema, type)) { - if (referenceObject instanceof Table && referenceSnapshot.getDatabase().isLiquibaseTable(referenceObject.getName())) { + if (referenceObject instanceof Table && referenceSnapshot.getDatabase().isLiquibaseTable(referenceSchema, referenceObject.getName())) { continue; } if (comparisonSnapshot.contains(comparisonSchema, referenceObject)) { @@ -88,7 +84,7 @@ protected void compareObjectType(Class type, Datab } for (T targetObject : comparisonSnapshot.getDatabaseObjects(comparisonSchema, type)) { - if (targetObject instanceof Table && comparisonSnapshot.getDatabase().isLiquibaseTable(targetObject.getName())) { + if (targetObject instanceof Table && comparisonSnapshot.getDatabase().isLiquibaseTable(comparisonSchema, targetObject.getName())) { continue; } if (!referenceSnapshot.contains(referenceSchema, targetObject)) { diff --git a/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java index 43b5c32ad13..7a6434f1a8e 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java @@ -530,7 +530,7 @@ protected void addChangedColumnChanges(List changes) { } protected boolean shouldModifyColumn(Column column) { - return !diffResult.getReferenceSnapshot().getDatabase().isLiquibaseTable(column.getRelation().getName()); + return !diffResult.getReferenceSnapshot().getDatabase().isLiquibaseTable(column.getRelation().getSchema(), column.getRelation().getName()); } @@ -610,8 +610,7 @@ protected void addMissingColumnChanges(List changes) { protected void addMissingTableChanges(List changes) { for (Table missingTable : diffResult.getObjectDiff(Table.class).getMissing()) { - if (diffResult.getReferenceSnapshot().getDatabase().isLiquibaseTable( - missingTable.getName())) { + if (diffResult.getReferenceSnapshot().getDatabase().isLiquibaseTable(missingTable.getSchema(), missingTable.getName())) { continue; } @@ -636,7 +635,7 @@ protected void addMissingTableChanges(List changes) { if (column.isPrimaryKey()) { PrimaryKey primaryKey = null; for (PrimaryKey pk : diffResult.getObjectDiff(PrimaryKey.class).getMissing()) { - if (diffResult.getComparisonSnapshot().getDatabase().objectNamesEqual(pk.getTable().getName(), missingTable.getName())) { + if (pk.getTable().equals(missingTable.getName(), diffResult.getComparisonSnapshot().getDatabase())) { primaryKey = pk; } } @@ -721,7 +720,7 @@ protected void addInsertDataChanges(List changeSets, String dataDir) try { for (Schema schema : diffResult.getReferenceSnapshot().getSchemas()) { for (Table table : diffResult.getReferenceSnapshot().getDatabaseObjects(schema, Table.class)) { - if (diffResult.getReferenceSnapshot().getDatabase().isLiquibaseTable(table.getName())) { + if (diffResult.getReferenceSnapshot().getDatabase().isLiquibaseTable(schema, table.getName())) { continue; } List changes = new ArrayList(); diff --git a/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java b/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java index 36cb490b24f..68521160c99 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java @@ -52,7 +52,7 @@ public T getDatabaseObject(Schema schema, String obje schema = database.correctSchema(schema); for (DatabaseObject object : getDatabaseObjects(schema, type)) { - if (database.objectNamesEqual(object.getName(), objectName)) { + if (object.equals(objectName, database)) { //noinspection unchecked return (T) object; } @@ -117,7 +117,7 @@ public boolean isPrimaryKey(Column column) { if (column.getRelation() == null) { continue; } - if (database.objectNamesEqual(pk.getTable().getName(), column.getRelation().getName())) { + if (pk.getTable().equals(column.getRelation(), database)) { if (pk.getColumnNamesAsList().contains(column.getName())) { return true; } diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/DerbyDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/DerbyDatabaseSnapshotGenerator.java index 8aa180b6dd3..6cd56a03296 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/DerbyDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/DerbyDatabaseSnapshotGenerator.java @@ -17,27 +17,27 @@ public int getPriority(Database database) { return PRIORITY_DATABASE; } - /** - * Derby seems to have troubles - */ - @Override - public boolean hasIndex(Schema schema, String tableName, String indexName, String columnNames, Database database) throws DatabaseException { - try { - ResultSet rs = getMetaData(database).getIndexInfo(schema.getCatalogName(), schema.getName(), "%", false, true); - while (rs.next()) { - if (database.objectNamesEqual(rs.getString("INDEX_NAME"), indexName)) { - return true; - } - if (tableName != null && columnNames != null) { - if (database.objectNamesEqual(tableName, rs.getString("TABLE_NAME")) && database.objectNamesEqual(columnNames.replaceAll(" ",""), rs.getString("COLUMN_NAME").replaceAll(" ",""))) { - return true; - } - } - } - return false; - } catch (SQLException e) { - throw new DatabaseException(e); - } - } +// /** +// * Derby seems to have troubles +// */ +// @Override +// public boolean hasIndex(Schema schema, String tableName, String indexName, String columnNames, Database database) throws DatabaseException { +// try { +// ResultSet rs = getMetaData(database).getIndexInfo(schema.getCatalogName(), schema.getName(), "%", false, true); +// while (rs.next()) { +// if (database.objectNamesEqual(rs.getString("INDEX_NAME"), indexName)) { +// return true; +// } +// if (tableName != null && columnNames != null) { +// if (database.objectNamesEqual(tableName, rs.getString("TABLE_NAME")) && database.objectNamesEqual(columnNames.replaceAll(" ",""), rs.getString("COLUMN_NAME").replaceAll(" ",""))) { +// return true; +// } +// } +// } +// return false; +// } catch (SQLException e) { +// throw new DatabaseException(e); +// } +// } } \ No newline at end of file diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java index 32598a33862..10db4181f81 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java @@ -356,18 +356,18 @@ protected void readTables(DatabaseSnapshot snapshot, Schema schema, DatabaseMeta try { while (tableMetaDataRs.next()) { Table table = readTable(tableMetaDataRs, database, false); - if (database.isLiquibaseTable(table.getName())) { - if (database.objectNamesEqual(table.getName(), database.getDatabaseChangeLogTableName())) { + if (database.isLiquibaseTable(schema, table.getName())) { + if (table.equals(database.getDatabaseChangeLogTableName(), database)) { snapshot.setDatabaseChangeLogTable(table); continue; } - if (database.objectNamesEqual(table.getName(), database.getDatabaseChangeLogLockTableName())) { + if (table.equals(database.getDatabaseChangeLogLockTableName(), database)) { snapshot.setDatabaseChangeLogLockTable(table); continue; } } - if (database.isSystemTable(table.getSchema(), table.getName())) { + if (database.isSystemTable(table.getSchema(), table.getName()) || database.isLiquibaseTable(table.getSchema(), table.getName())) { continue; } @@ -664,21 +664,22 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin } } + Index index = new Index(); + index.setTable((Table) new Table(tableName).setSchema(schema)); + index.setName(indexName); if (columnNames != null) { - columnNames = columnNames.replace(" ", ""); - if (columnNames.contains(",")) { - List fixedColumnNames = new ArrayList(); - for (String columnName : columnNames.split(",")) { - fixedColumnNames.add(database.correctColumnName(columnName)); - } - columnNames = StringUtils.join(fixedColumnNames, ","); + for (String column : columnNames.split("\\s*,\\s*")) { + index.getColumns().add(column); } + } + + if (columnNames != null) { Map> columnsByIndexName = new HashMap>(); ResultSet rs = getMetaData(database).getIndexInfo(schema.getCatalogName(), schema.getName(), database.correctTableName(tableName), false, true); try { while (rs.next()) { String foundIndexName = rs.getString("INDEX_NAME"); - if (indexName != null && !database.objectNamesEqual(foundIndexName, indexName)) { + if (indexName != null && indexName.equalsIgnoreCase(foundIndexName)) { //ok to use equalsIgnoreCase because we will check case later continue; } short ordinalPosition = rs.getShort("ORDINAL_POSITION"); @@ -686,16 +687,21 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin if (!columnsByIndexName.containsKey(foundIndexName)) { columnsByIndexName.put(foundIndexName, new TreeMap()); } - String columnName = database.correctColumnName(rs.getString("COLUMN_NAME")); + String columnName = rs.getString("COLUMN_NAME"); Map columns = columnsByIndexName.get(foundIndexName); columns.put(ordinalPosition, columnName); } - for (TreeMap columnList : columnsByIndexName.values()) { + for (Map.Entry> foundIndexData : columnsByIndexName.entrySet()) { + Index foundIndex = new Index() + .setName(foundIndexData.getKey()) + .setTable(((Table) new Table(tableName).setSchema(schema))); + foundIndex.getColumns().addAll(foundIndexData.getValue().values()); - if (database.objectNamesEqual(StringUtils.join(columnList.values(), ","), columnNames)) { + if (foundIndex.equals(index, database)) { return true; } + return false; } return false; } finally { @@ -705,7 +711,10 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin ResultSet rs = getMetaData(database).getIndexInfo(schema.getCatalogName(), schema.getName(), database.correctTableName(tableName), false, true); try { while (rs.next()) { - if (database.objectNamesEqual(rs.getString("INDEX_NAME"), database.correctIndexName(indexName))) { + Index foundIndex = new Index() + .setName(rs.getString("INDEX_NAME")) + .setTable(((Table) new Table(tableName).setSchema(schema))); + if (foundIndex.equals(index, database)) { return true; } } @@ -725,11 +734,13 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin } public boolean hasForeignKey(Schema schema, String foreignKeyTableName, String fkName, Database database) throws DatabaseException { + ForeignKey fk = new ForeignKey().setName(fkName); try { ResultSet rs = getMetaData(database).getImportedKeys(schema.getCatalogName(), schema.getName(), database.correctTableName(foreignKeyTableName)); try { while (rs.next()) { - if (database.objectNamesEqual(rs.getString("FK_NAME"), database.correctForeignKeyName(fkName))) { + ForeignKey foundFk = new ForeignKey().setName(rs.getString("FK_NAME")); + if (fk.equals(foundFk, database)) { return true; } } @@ -933,17 +944,17 @@ protected void readIndexes(DatabaseSnapshot snapshot, Schema schema, DatabaseMet * */ for (Index index : snapshot.getDatabaseObjects(schema, Index.class)) { for (PrimaryKey pk : snapshot.getDatabaseObjects(schema, PrimaryKey.class)) { - if (database.objectNamesEqual(index.getTable().getName(), pk.getTable().getName()) && database.objectNamesEqual(index.getColumnNames(), pk.getColumnNames())) { + if (index.getTable().equals(pk.getTable().getName(), database) && columnNamesAreEqual(index.getColumnNames(), pk.getColumnNames(), database)) { index.addAssociatedWith(Index.MARK_PRIMARY_KEY); } } for (ForeignKey fk : snapshot.getDatabaseObjects(schema, ForeignKey.class)) { - if (database.objectNamesEqual(index.getTable().getName(), fk.getForeignKeyTable().getName()) && database.objectNamesEqual(index.getColumnNames(), fk.getForeignKeyColumns())) { + if (index.getTable().equals(fk.getForeignKeyTable().getName(), database) && columnNamesAreEqual(index.getColumnNames(), fk.getForeignKeyColumns(), database)) { index.addAssociatedWith(Index.MARK_FOREIGN_KEY); } } for (UniqueConstraint uc : snapshot.getDatabaseObjects(schema, UniqueConstraint.class)) { - if (database.objectNamesEqual(index.getTable().getName(), uc.getTable().getName()) && database.objectNamesEqual(index.getColumnNames(), uc.getColumnNames())) { + if (index.getTable().equals(uc.getTable()) && columnNamesAreEqual(index.getColumnNames(), uc.getColumnNames(), database)) { index.addAssociatedWith(Index.MARK_UNIQUE_CONSTRAINT); } } @@ -952,6 +963,14 @@ protected void readIndexes(DatabaseSnapshot snapshot, Schema schema, DatabaseMet snapshot.removeDatabaseObjects(schema, indexesToRemove.toArray(new Index[indexesToRemove.size()])); } + protected boolean columnNamesAreEqual(String columnNames, String otherColumnNames, Database database) { + if (database.isCaseSensitive()) { + return columnNames.replace(" ", "").equals(otherColumnNames.replace(" ", "")); + } else { + return columnNames.replace(" ", "").equalsIgnoreCase(otherColumnNames.replace(" ", "")); + } + } + protected boolean includeInSnapshot(DatabaseObject obj) { return true; } @@ -972,13 +991,13 @@ protected void readPrimaryKeys(DatabaseSnapshot snapshot, Schema schema, Databas String columnName = cleanObjectNameFromDatabase(rs.getString("COLUMN_NAME")); short position = rs.getShort("KEY_SEQ"); - if (database.isLiquibaseTable(tableName)) { + if (database.isLiquibaseTable(schema, tableName)) { continue; } boolean foundExistingPK = false; for (PrimaryKey pk : foundPKs) { - if (database.objectNamesEqual(pk.getTable().getName(), tableName)) { + if (pk.getTable().equals(tableName, database)) { pk.addColumnName(position - 1, columnName); foundExistingPK = true; diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java index 6ccf00bc3f5..4e0df296daa 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/OracleDatabaseSnapshotGenerator.java @@ -9,8 +9,6 @@ import liquibase.util.JdbcUtils; import java.sql.*; -import java.util.ArrayList; -import java.util.List; import java.util.Map; import java.util.HashMap; @@ -365,21 +363,23 @@ protected void readIndexes(DatabaseSnapshot snapshot, Schema schema, DatabaseMet * */ for (Index index : snapshot.getDatabaseObjects(schema, Index.class)) { for (PrimaryKey pk : snapshot.getDatabaseObjects(schema, PrimaryKey.class)) { - if (database.objectNamesEqual(index.getTable().getName(), pk.getTable().getName()) && database.objectNamesEqual(index.getColumnNames(), pk.getColumnNames())) { + if (index.getTable().equals(pk.getTable().getName(), database) && columnNamesAreEqual(index.getColumnNames(), pk.getColumnNames(), database)) { index.addAssociatedWith(Index.MARK_PRIMARY_KEY); } } for (ForeignKey fk : snapshot.getDatabaseObjects(schema, ForeignKey.class)) { - if (database.objectNamesEqual(index.getTable().getName(), fk.getForeignKeyTable().getName()) && database.objectNamesEqual(index.getColumnNames(), fk.getForeignKeyColumns())) { + if (index.getTable().equals(fk.getForeignKeyTable().getName(), database) && columnNamesAreEqual(index.getColumnNames(), fk.getForeignKeyColumns(), database)) { index.addAssociatedWith(Index.MARK_FOREIGN_KEY); } } for (UniqueConstraint uc : snapshot.getDatabaseObjects(schema, UniqueConstraint.class)) { - if (database.objectNamesEqual(index.getTable().getName(), uc.getTable().getName()) && database.objectNamesEqual(index.getColumnNames(), uc.getColumnNames())) { + if (index.getTable().equals(uc.getTable()) && columnNamesAreEqual(index.getColumnNames(), uc.getColumnNames(), database)) { index.addAssociatedWith(Index.MARK_UNIQUE_CONSTRAINT); } } + } + } // // @Override diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/PostgresDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/PostgresDatabaseSnapshotGenerator.java index c906e1cfb2f..cc63bafb093 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/PostgresDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/PostgresDatabaseSnapshotGenerator.java @@ -54,7 +54,7 @@ protected void readUniqueConstraints(DatabaseSnapshot snapshot, Schema schema, D String tableName = rs.getString("relname"); UniqueConstraint constraintInformation = new UniqueConstraint(); constraintInformation.setName(constraintName); - if(!database.isSystemTable(schema, tableName)&&!database.isLiquibaseTable(tableName)) { + if(!database.isSystemTable(schema, tableName)&&!database.isLiquibaseTable(schema, tableName)) { Table table = snapshot.getDatabaseObject(schema, tableName, Table.class); if (table == null) { // SKip it -- the query above pulls back more then the query for tables & views in the super class diff --git a/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java b/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java index 9feb9e8bb77..c73caf2f9d2 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java +++ b/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java @@ -50,6 +50,14 @@ public DatabaseObject[] getContainingObjects() { return null; } + public boolean equals(DatabaseObject otherObject, Database accordingTo) { + return otherObject.getName().equalsIgnoreCase(this.getName()); + } + + public boolean equals(String otherObjectName, Database accordingTo) { + return otherObjectName.equalsIgnoreCase(this.getName()); + } + public void setCanCacheLiquibaseTableInfo(boolean canCacheLiquibaseTableInfo) { // } @@ -93,10 +101,6 @@ public boolean isCaseSensitive() { return false; } - public boolean objectNamesEqual(String name1, String name2) { - return name1.equalsIgnoreCase(name2); - } - public void setAutoCommit(boolean b) throws DatabaseException { } @@ -282,7 +286,7 @@ public boolean isSystemView(Schema schema, String name) { return false; } - public boolean isLiquibaseTable(String tableName) { + public boolean isLiquibaseTable(Schema schema, String tableName) { return false; } diff --git a/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java b/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java index 5b42fd6b325..042278c6ff0 100644 --- a/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java +++ b/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java @@ -450,7 +450,7 @@ public void testRerunDiffChangeLog() throws Exception { } DatabaseSnapshot emptyAgainSnapshot = DatabaseSnapshotGeneratorFactory.getInstance().createSnapshot(database, new DiffControl()); - assertEquals(1, emptyAgainSnapshot.getDatabaseObjects(migratedSnapshot.getSchemas().iterator().next(), Table.class).size()); + assertEquals(0, emptyAgainSnapshot.getDatabaseObjects(migratedSnapshot.getSchemas().iterator().next(), Table.class).size()); assertEquals(0, emptyAgainSnapshot.getDatabaseObjects(migratedSnapshot.getSchemas().iterator().next(), View.class).size()); } } From c785b3ff5d5637220acbc1c178af720feaf8be70 Mon Sep 17 00:00:00 2001 From: "nathan.voxland" Date: Wed, 22 Aug 2012 03:01:03 -0500 Subject: [PATCH 08/11] Changing schema/catalog logic and introducing DatabaseSpecific implementations of them --- .../liquibase/database/AbstractDatabase.java | 21 +++-- .../liquibase/database/core/DB2Database.java | 5 ++ .../database/core/MySQLDatabase.java | 5 ++ .../liquibase/database/structure/Catalog.java | 23 +++++- .../liquibase/database/structure/Schema.java | 77 ++++++++++++++----- .../liquibase/datatype/core/BigIntType.java | 4 + .../liquibase/datatype/core/DoubleType.java | 4 + .../java/liquibase/datatype/core/IntType.java | 4 + .../liquibase/datatype/core/SmallIntType.java | 13 ++++ .../liquibase/snapshot/DatabaseSnapshot.java | 1 + .../jvm/JdbcDatabaseSnapshotGenerator.java | 3 + .../db2/rollback/rollbackable.changelog.xml | 2 +- 12 files changed, 131 insertions(+), 31 deletions(-) diff --git a/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java b/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java index 1bb5d40a8b5..9019a525e6d 100644 --- a/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java @@ -196,29 +196,36 @@ protected String doGetDefaultCatalogName() throws DatabaseException { } public Schema correctSchema(Schema schema) { + if (schema instanceof Schema.DatabaseSpecific && ((Schema.DatabaseSpecific) schema).getDatabase().equals(this)) { + return schema; + } if (schema == null) { - schema = new Schema(getDefaultCatalogName(), getDefaultSchemaName()); + schema = new Schema.DatabaseSpecific(getDefaultCatalogName(), getDefaultSchemaName(), this); } String catalogName = schema.getCatalogName(); String schemaName = schema.getName(); - if (catalogName == null) { - catalogName = getDefaultCatalogName(); + if (supportsCatalogs()) { + if (catalogName.equals(Catalog.DEFAULT_NAME)) { + catalogName = getDefaultCatalogName(); + } else { + catalogName = correctObjectName(catalogName); + } } else { - catalogName = correctObjectName(catalogName); + catalogName = null; } if (supportsSchemas()) { - if (schemaName == null) { + if (schemaName.equals(Schema.DEFAULT_NAME)) { schemaName = getDefaultSchemaName(); } else { schemaName = correctObjectName(schemaName); } } else { - schemaName = catalogName; + schemaName = null; } - return new Schema(catalogName, schemaName); + return new Schema.DatabaseSpecific(catalogName, schemaName, this); } public String correctTableName(String tableName) { diff --git a/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java b/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java index 7dbc443531a..d9e81c7a27c 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java +++ b/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java @@ -39,6 +39,11 @@ public Integer getDefaultPort() { @Override public boolean supportsSchemas() { + return true; + } + + @Override + public boolean supportsCatalogs() { return false; } diff --git a/liquibase-core/src/main/java/liquibase/database/core/MySQLDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/MySQLDatabase.java index 872f86692b5..8863624916b 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/MySQLDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/MySQLDatabase.java @@ -137,6 +137,11 @@ public boolean supportsSchemas() { return false; } + @Override + public boolean supportsCatalogs() { + return true; + } + @Override public String escapeIndexName(String catalogName, String schemaName, String indexName) { return escapeDatabaseObject(indexName); diff --git a/liquibase-core/src/main/java/liquibase/database/structure/Catalog.java b/liquibase-core/src/main/java/liquibase/database/structure/Catalog.java index 8658938fa18..e55fb06d02f 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/Catalog.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/Catalog.java @@ -1,5 +1,6 @@ package liquibase.database.structure; +import liquibase.database.Database; import liquibase.util.StringUtils; public class Catalog { @@ -7,7 +8,7 @@ public class Catalog { public static final String DEFAULT_NAME = "!DEFAULT_CATALOG!"; public static final Catalog DEFAULT = new Catalog(DEFAULT_NAME); - private String name; + protected String name; public Catalog(String name) { if (StringUtils.trimToNull(name) == null) { @@ -18,9 +19,6 @@ public Catalog(String name) { } public String getName() { - if (name.equals(DEFAULT_NAME)) { - return null; - } return name; } @@ -40,4 +38,21 @@ public boolean equals(Object o) { public int hashCode() { return name != null ? name.hashCode() : 0; } + + public static class DatabaseSpecific extends Catalog { + private Database database; + + public DatabaseSpecific(String name, Database database) { + super(name); + this.database = database; + if (name == null) { + this.name = null; + } + } + + public Database getDatabase() { + return database; + } + + } } diff --git a/liquibase-core/src/main/java/liquibase/database/structure/Schema.java b/liquibase-core/src/main/java/liquibase/database/structure/Schema.java index a608e2956cb..3aa6406f765 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/Schema.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/Schema.java @@ -1,5 +1,6 @@ package liquibase.database.structure; +import liquibase.database.Database; import liquibase.util.StringUtils; public class Schema extends DatabaseObjectImpl { @@ -7,35 +8,43 @@ public class Schema extends DatabaseObjectImpl { public static final String DEFAULT_NAME = "!DEFAULT_SCHEMA!"; public static final Schema DEFAULT = new Schema(Catalog.DEFAULT, DEFAULT_NAME); - private Catalog catalog; - private String name; + protected Catalog catalog; + protected String name; public DatabaseObject[] getContainingObjects() { return null; } public Schema(String catalog, String schemaName) { - if (StringUtils.trimToNull(schemaName) == null) { - this.name = DEFAULT_NAME; - } else { - this.name = schemaName; + catalog = StringUtils.trimToNull(catalog); + schemaName = StringUtils.trimToNull(schemaName); + + if (catalog == null && schemaName == null) { + catalog = Catalog.DEFAULT_NAME; + schemaName = Schema.DEFAULT_NAME; + } else if (schemaName != null && catalog == null) { + if (schemaName.equals(Schema.DEFAULT_NAME)) { + catalog = Catalog.DEFAULT_NAME; + } else { + catalog = schemaName; + } + } else if (catalog != null && schemaName == null) { + if (catalog.equals(Catalog.DEFAULT_NAME)) { + schemaName = Schema.DEFAULT_NAME; + } else { + schemaName = catalog; + } } + + this.name = schemaName; this.catalog = new Catalog(catalog); } public Schema(Catalog catalog, String name) { - if (StringUtils.trimToNull(name) == null) { - this.name = DEFAULT_NAME; - } else { - this.name = name; - } - this.catalog = catalog; + this(catalog.getName(), name); } public String getName() { - if (name.equals(DEFAULT_NAME)) { - return null; - } return name; } @@ -54,16 +63,16 @@ public boolean equals(Object o) { Schema schema = (Schema) o; - if (!catalog.equals(schema.catalog)) return false; - if (!name.equals(schema.name)) return false; + if (catalog != null ? !catalog.equals(schema.catalog) : schema.catalog != null) return false; + if (name != null ? !name.equals(schema.name) : schema.name != null) return false; return true; } @Override public int hashCode() { - int result = catalog.hashCode(); - result = 31 * result + name.hashCode(); + int result = catalog != null ? catalog.hashCode() : 0; + result = 31 * result + (name != null ? name.hashCode() : 0); return result; } @@ -75,4 +84,34 @@ public String getCatalogName() { public String toString() { return catalog.getName()+"."+name; } + + public static class DatabaseSpecific extends Schema { + private Database database; + + public DatabaseSpecific(String catalog, String schemaName, Database database) { + super(catalog, schemaName); + this.database = database; + if (catalog == null) { + this.catalog = new Catalog.DatabaseSpecific(null, database); + } + if (schemaName == null) { + this.name = null; + } + } + + public DatabaseSpecific(Catalog catalog, String name) { + super(catalog, name); + this.database = database; + if (catalog == null) { + this.catalog = new Catalog.DatabaseSpecific(null, database); + } + if (name == null) { + this.name = null; + } + } + + public Database getDatabase() { + return database; + } + } } diff --git a/liquibase-core/src/main/java/liquibase/datatype/core/BigIntType.java b/liquibase-core/src/main/java/liquibase/datatype/core/BigIntType.java index 966185abca1..99dab4e9beb 100644 --- a/liquibase-core/src/main/java/liquibase/datatype/core/BigIntType.java +++ b/liquibase-core/src/main/java/liquibase/datatype/core/BigIntType.java @@ -1,6 +1,7 @@ package liquibase.datatype.core; import liquibase.database.Database; +import liquibase.database.core.DB2Database; import liquibase.database.core.InformixDatabase; import liquibase.database.core.OracleDatabase; import liquibase.datatype.DataTypeInfo; @@ -32,6 +33,9 @@ public DatabaseDataType toDatabaseDataType(Database database) { if (database instanceof OracleDatabase) { return new DatabaseDataType("NUMBER", 38,0); } + if (database instanceof DB2Database) { + return new DatabaseDataType("BIGINT"); + } return super.toDatabaseDataType(database); } } diff --git a/liquibase-core/src/main/java/liquibase/datatype/core/DoubleType.java b/liquibase-core/src/main/java/liquibase/datatype/core/DoubleType.java index c34a4516465..303f4545081 100644 --- a/liquibase-core/src/main/java/liquibase/datatype/core/DoubleType.java +++ b/liquibase-core/src/main/java/liquibase/datatype/core/DoubleType.java @@ -1,6 +1,7 @@ package liquibase.datatype.core; import liquibase.database.Database; +import liquibase.database.core.DB2Database; import liquibase.database.core.MSSQLDatabase; import liquibase.database.core.OracleDatabase; import liquibase.database.core.PostgresDatabase; @@ -15,6 +16,9 @@ public DatabaseDataType toDatabaseDataType(Database database) { if (database instanceof MSSQLDatabase) { return new DatabaseDataType("FLOAT"); } + if (database instanceof DB2Database) { + return new DatabaseDataType("DOUBLE"); + } if (database instanceof OracleDatabase) { return new DatabaseDataType("FLOAT", 24); } diff --git a/liquibase-core/src/main/java/liquibase/datatype/core/IntType.java b/liquibase-core/src/main/java/liquibase/datatype/core/IntType.java index b868aa47c23..dcee4f43e0b 100644 --- a/liquibase-core/src/main/java/liquibase/datatype/core/IntType.java +++ b/liquibase-core/src/main/java/liquibase/datatype/core/IntType.java @@ -1,6 +1,7 @@ package liquibase.datatype.core; import liquibase.database.Database; +import liquibase.database.core.DB2Database; import liquibase.database.core.InformixDatabase; import liquibase.database.core.OracleDatabase; import liquibase.datatype.DataTypeInfo; @@ -29,6 +30,9 @@ public DatabaseDataType toDatabaseDataType(Database database) { if (database instanceof OracleDatabase) { return new DatabaseDataType("INTEGER", getParameters()); } + if (database instanceof DB2Database) { + return new DatabaseDataType("INTEGER"); + } return super.toDatabaseDataType(database); } diff --git a/liquibase-core/src/main/java/liquibase/datatype/core/SmallIntType.java b/liquibase-core/src/main/java/liquibase/datatype/core/SmallIntType.java index 7199eeaf0de..c0207052a77 100644 --- a/liquibase-core/src/main/java/liquibase/datatype/core/SmallIntType.java +++ b/liquibase-core/src/main/java/liquibase/datatype/core/SmallIntType.java @@ -1,12 +1,25 @@ package liquibase.datatype.core; import liquibase.database.Database; +import liquibase.database.core.DB2Database; +import liquibase.database.core.MSSQLDatabase; +import liquibase.database.core.OracleDatabase; +import liquibase.database.core.PostgresDatabase; import liquibase.datatype.DataTypeInfo; +import liquibase.datatype.DatabaseDataType; import liquibase.datatype.LiquibaseDataType; @DataTypeInfo(name="smallint", aliases = "java.sql.Types.SMALLINT", minParameters = 0, maxParameters = 1, priority = LiquibaseDataType.PRIORITY_DEFAULT) public class SmallIntType extends LiquibaseDataType { + @Override + public DatabaseDataType toDatabaseDataType(Database database) { + if (database instanceof DB2Database) { + return new DatabaseDataType("SMALLINT"); + } + return super.toDatabaseDataType(database); + } + @Override public String objectToString(Object value, Database database) { if (value == null || value.toString().equalsIgnoreCase("null")) { diff --git a/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java b/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java index 68521160c99..e7c8b88c7db 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/DatabaseSnapshot.java @@ -83,6 +83,7 @@ public void addDatabaseObjects(DatabaseObject... objects) { for (DatabaseObject object : objects) { Schema schema = object.getSchema(); + schema = database.correctSchema(schema); if (!schemaSnapshots.containsKey(schema)) { addSchema(schema); diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java index 10db4181f81..94da030d147 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java @@ -714,6 +714,9 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin Index foundIndex = new Index() .setName(rs.getString("INDEX_NAME")) .setTable(((Table) new Table(tableName).setSchema(schema))); + if (foundIndex.getName() == null) { + continue; + } if (foundIndex.equals(index, database)) { return true; } diff --git a/liquibase-integration-tests/src/test/resources/changelogs/db2/rollback/rollbackable.changelog.xml b/liquibase-integration-tests/src/test/resources/changelogs/db2/rollback/rollbackable.changelog.xml index 87dd7cac10b..43219d25131 100644 --- a/liquibase-integration-tests/src/test/resources/changelogs/db2/rollback/rollbackable.changelog.xml +++ b/liquibase-integration-tests/src/test/resources/changelogs/db2/rollback/rollbackable.changelog.xml @@ -112,7 +112,7 @@ + newTableName="sku" newColumnName="code" newColumnDataType="varchar(50)"/> From 8f7ee1c24bbd1405a49b9d02394da2ca2b60f389 Mon Sep 17 00:00:00 2001 From: Steve Suehs Date: Fri, 24 Aug 2012 09:49:27 -0500 Subject: [PATCH 09/11] Add missing column for SCOPE_CATALOG. --- .../liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java index 94da030d147..ff664e7d52e 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java @@ -478,11 +478,13 @@ private Map convertResultSetToMap(ResultSet rs) throws SQLExcept String.class, String.class, short.class, + String.class, String.class }; Map data = new HashMap(); for (int i=1; i<= rs.getMetaData().getColumnCount(); i++) { + //System.err.println("" + i + " " + rs.getMetaData().getColumnName(i) + " is a " + rs.getMetaData().getColumnType(i) + " " + rs.getMetaData().getColumnTypeName(i)); Class classType = types[i]; Object value; if (classType.equals(String.class)) { From 4c9f4e494ab3d1e0e85f6e5396e9bbd7ba9b87fd Mon Sep 17 00:00:00 2001 From: Steve Suehs Date: Fri, 24 Aug 2012 10:22:52 -0500 Subject: [PATCH 10/11] delete println --- .../liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java | 1 - 1 file changed, 1 deletion(-) diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java index ff664e7d52e..aa8ebc4594c 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java @@ -484,7 +484,6 @@ private Map convertResultSetToMap(ResultSet rs) throws SQLExcept Map data = new HashMap(); for (int i=1; i<= rs.getMetaData().getColumnCount(); i++) { - //System.err.println("" + i + " " + rs.getMetaData().getColumnName(i) + " is a " + rs.getMetaData().getColumnType(i) + " " + rs.getMetaData().getColumnTypeName(i)); Class classType = types[i]; Object value; if (classType.equals(String.class)) { From 8e9c63ba04976834544cf9490d51ac4840da68c5 Mon Sep 17 00:00:00 2001 From: "nathan.voxland" Date: Tue, 28 Aug 2012 02:49:35 -0500 Subject: [PATCH 11/11] Fixing various failing integration database tests, especially around catalog/schema logic --- .../change/core/LoadUpdateDataChange.java | 2 +- .../liquibase/database/AbstractDatabase.java | 101 +++++++++++++--- .../java/liquibase/database/Database.java | 9 ++ .../liquibase/database/core/DB2Database.java | 10 +- .../liquibase/database/core/HsqlDatabase.java | 5 + .../database/core/MSSQLDatabase.java | 18 +++ .../database/core/MySQLDatabase.java | 21 ---- .../structure/DatabaseObjectImpl.java | 3 + .../liquibase/database/structure/Schema.java | 2 +- .../liquibase/datatype/core/NCharType.java | 24 ++++ .../{NumericType.java => NumberType.java} | 40 ++++--- .../diff/output/DiffToChangeLog.java | 22 +++- .../liquibase/lockservice/LockService.java | 10 +- .../jvm/DB2DatabaseSnapshotGenerator.java | 15 +++ .../jvm/H2DatabaseSnapshotGenerator.java | 1 + .../jvm/HsqlDatabaseSnapshotGenerator.java | 7 ++ .../jvm/JdbcDatabaseSnapshotGenerator.java | 109 ++++++++++-------- .../sqlgenerator/core/AddColumnGenerator.java | 2 +- .../core/CreateTableGenerator.java | 2 +- .../core/CreateViewGenerator.java | 11 +- .../core/GetViewDefinitionGenerator.java | 29 +++-- .../core/GetViewDefinitionGeneratorDB2.java | 2 +- .../core/GetViewDefinitionGeneratorHsql.java | 2 +- ...nitionGeneratorInformationSchemaViews.java | 33 ------ .../core/SelectSequencesGeneratorDB2.java | 2 +- .../core/StoredProcedureGenerator.java | 12 +- .../liquibase/database/core/MockDatabase.java | 16 +++ .../dbtest/AbstractIntegrationTest.java | 17 ++- .../dbtest/hsqldb/HsqlIntegrationTest.java | 10 -- .../dbtest/mssql/MssqlIntegrationTest.java | 7 +- .../rollback/rollbackable.changelog.xml | 2 +- 31 files changed, 364 insertions(+), 182 deletions(-) create mode 100644 liquibase-core/src/main/java/liquibase/datatype/core/NCharType.java rename liquibase-core/src/main/java/liquibase/datatype/core/{NumericType.java => NumberType.java} (75%) delete mode 100644 liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorInformationSchemaViews.java diff --git a/liquibase-core/src/main/java/liquibase/change/core/LoadUpdateDataChange.java b/liquibase-core/src/main/java/liquibase/change/core/LoadUpdateDataChange.java index aa406aed16a..c6c102c5493 100644 --- a/liquibase-core/src/main/java/liquibase/change/core/LoadUpdateDataChange.java +++ b/liquibase-core/src/main/java/liquibase/change/core/LoadUpdateDataChange.java @@ -66,7 +66,7 @@ private String getWhereClause(InsertOrUpdateStatement insertOrUpdateStatement, D { where.append(database.escapeColumnName(insertOrUpdateStatement.getCatalogName(), insertOrUpdateStatement.getSchemaName(), insertOrUpdateStatement.getTableName(), thisPkColumn) + " = " ); Object newValue = insertOrUpdateStatement.getColumnValues().get(thisPkColumn); - where.append(DataTypeFactory.getInstance().fromObject(newValue, database)); + where.append(DataTypeFactory.getInstance().fromObject(newValue, database).objectToString(newValue, database)); where.append(" AND "); } diff --git a/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java b/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java index 9019a525e6d..643f6bd7321 100644 --- a/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/AbstractDatabase.java @@ -200,34 +200,80 @@ public Schema correctSchema(Schema schema) { return schema; } if (schema == null) { - schema = new Schema.DatabaseSpecific(getDefaultCatalogName(), getDefaultSchemaName(), this); + return new Schema.DatabaseSpecific(getDefaultCatalogName(), getDefaultSchemaName(), this); } String catalogName = schema.getCatalogName(); String schemaName = schema.getName(); - if (supportsCatalogs()) { + if (supportsCatalogs() && supportsSchemas()) { if (catalogName.equals(Catalog.DEFAULT_NAME)) { catalogName = getDefaultCatalogName(); } else { catalogName = correctObjectName(catalogName); } - } else { - catalogName = null; - } - if (supportsSchemas()) { if (schemaName.equals(Schema.DEFAULT_NAME)) { schemaName = getDefaultSchemaName(); } else { schemaName = correctObjectName(schemaName); } - } else { - schemaName = null; + } else if (!supportsCatalogs() && !supportsSchemas()) { + return new Schema.DatabaseSpecific("DEFAULT", "DEFAULT", this); + } else if (supportsCatalogs()) { //schema is null + if (catalogName.equals(Catalog.DEFAULT_NAME)) { + if (Schema.DEFAULT_NAME.equals(schemaName)) { + catalogName = getDefaultCatalogName(); + } else { + catalogName = schemaName; + } + } + schemaName = catalogName; + } else if (supportsSchemas()) { + if (schemaName.equals(Schema.DEFAULT_NAME)) { + if (Catalog.DEFAULT_NAME.equals(catalogName)) { + schemaName = getDefaultSchemaName(); + } else { + schemaName = catalogName; + } + } + catalogName = schemaName; } - return new Schema.DatabaseSpecific(catalogName, schemaName, this); } + + public String getAssumedCatalogName(String catalogName, String schemaName) { + if (this.supportsCatalogs()) { + if (catalogName == null) { + if (this.supportsSchemas()) { + return null; + } else { + return schemaName; + } + } else { + return catalogName; + } + } else { + return null; + } + } + + public String getAssumedSchemaName(String catalogName, String schemaName) { + if (this.supportsSchemas()) { + if (schemaName == null) { + if (this.supportsCatalogs()) { + return null; + } else { + return catalogName; + } + } else { + return schemaName; + } + } else { + return null; + } + } + public String correctTableName(String tableName) { return correctObjectName(tableName); } @@ -830,6 +876,9 @@ public boolean isSystemView(Schema schema, String viewName) { } public boolean isLiquibaseTable(Schema schema, String tableName) { + if (!schema.equals(correctSchema(new Schema(getLiquibaseCatalogName(), getLiquibaseSchemaName())), this)) { + return false; + } if (isCaseSensitive()) { return tableName.equals(this.getDatabaseChangeLogTableName()) || tableName.equals(this.getDatabaseChangeLogLockTableName()); } else { @@ -890,14 +939,30 @@ public String getViewDefinition(Schema schema, String viewName) throws DatabaseE } public String escapeTableName(String catalogName, String schemaName, String tableName) { - if (schemaName == null) { - schemaName = getDefaultSchemaName(); + if (catalogName == null && schemaName == null) { + return escapeDatabaseObject(tableName); } - - if (StringUtils.trimToNull(schemaName) == null || !supportsSchemas()) { + if (!supportsCatalogs() && !supportsSchemas()) { return escapeDatabaseObject(tableName); + } else if (supportsCatalogs() && supportsSchemas()) { +// Schema schema = correctSchema(new Schema(catalogName, schemaName)); +// return escapeDatabaseObject(schema.getCatalogName())+"."+escapeDatabaseObject(schema.getName())+"."+escapeDatabaseObject(tableName); + catalogName = StringUtils.trimToNull(catalogName); + schemaName = StringUtils.trimToNull(schemaName); + if (catalogName == null && schemaName == null) { + return escapeDatabaseObject(tableName); + } else if (catalogName == null) { + return escapeDatabaseObject(schemaName)+"."+escapeDatabaseObject(tableName); + } else { + return escapeDatabaseObject(catalogName)+"."+escapeDatabaseObject(schemaName)+"."+escapeDatabaseObject(tableName); + } } else { - return escapeDatabaseObject(schemaName) + "." + escapeDatabaseObject(tableName); + catalogName = getAssumedCatalogName(catalogName, schemaName); + if (StringUtils.trimToNull(catalogName) == null) { + return escapeDatabaseObject(tableName); + } else { + return escapeDatabaseObject(catalogName)+"."+escapeDatabaseObject(tableName); + } } } @@ -913,6 +978,14 @@ public String escapeIndexName(String catalogName, String schemaName, String inde } } + public String escapeSchemaName(String schemaName) { + return escapeDatabaseObject(schemaName); + } + + public String escapeCatalogName(String name) { + return escapeDatabaseObject(name); + } + public String escapeSequenceName(String catalogName, String schemaName, String sequenceName) { if (schemaName == null) { schemaName = getDefaultSchemaName(); diff --git a/liquibase-core/src/main/java/liquibase/database/Database.java b/liquibase-core/src/main/java/liquibase/database/Database.java index bfe5791de74..b266a2f4154 100644 --- a/liquibase-core/src/main/java/liquibase/database/Database.java +++ b/liquibase-core/src/main/java/liquibase/database/Database.java @@ -175,6 +175,10 @@ public interface Database extends DatabaseObject, PrioritizedService { String escapeDatabaseObject(String objectName); + String escapeSchemaName(String schemaName); + + String escapeCatalogName(String name); + /** * Escapes a single column name in a database-dependent manner so reserved words can be used as a column * name (i.e. "return"). @@ -287,4 +291,9 @@ public interface Database extends DatabaseObject, PrioritizedService { String correctForeignKeyName(String fkName); String correctIndexName(String indexName); + + String getAssumedSchemaName(String catalogName, String schemaName); + + String getAssumedCatalogName(String catalogName, String schemaName); + } diff --git a/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java b/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java index d9e81c7a27c..d9cbdb6a4b6 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java +++ b/liquibase-core/src/main/java/liquibase/database/core/DB2Database.java @@ -39,12 +39,12 @@ public Integer getDefaultPort() { @Override public boolean supportsSchemas() { - return true; + return false; } @Override public boolean supportsCatalogs() { - return false; + return true; } @Override @@ -57,7 +57,7 @@ public String getTypeName() { } @Override - public String getDefaultSchemaName() { + public String getDefaultCatalogName() { if( defaultSchemaName == null ) { Statement stmt = null; ResultSet rs = null; @@ -201,4 +201,8 @@ public String escapeIndexName(String catalogName, String schemaName, String inde return super.escapeIndexName(null, null, indexName); } + @Override + public String getAssumedCatalogName(String catalogName, String schemaName) { + return schemaName; + } } diff --git a/liquibase-core/src/main/java/liquibase/database/core/HsqlDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/HsqlDatabase.java index 198c7c02420..3344e9c3db3 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/HsqlDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/HsqlDatabase.java @@ -58,6 +58,11 @@ protected String correctObjectName(String objectName) { return objectName.toUpperCase(); } + @Override + public boolean supportsCatalogs() { + return false; + } + @Override public boolean supportsSequences() { return true; diff --git a/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java index 4c855952fe9..5ef99da7e07 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/MSSQLDatabase.java @@ -15,6 +15,7 @@ import java.util.regex.Pattern; import liquibase.database.jvm.JdbcConnection; import liquibase.logging.LogFactory; +import liquibase.util.StringUtils; /** * Encapsulates MS-SQL database support. @@ -275,4 +276,21 @@ public String getViewDefinition(Schema schema, String viewName) throws DatabaseE } return CREATE_VIEW_AS_PATTERN.matcher(definition).replaceFirst(""); } + + /** + * SQLServer does not support specifying teh database name as a prefix to the object name + * @return + */ + @Override + public String escapeViewName(String catalogName, String schemaName, String viewName) { + schemaName = getAssumedSchemaName(catalogName, schemaName); + if (StringUtils.trimToNull(schemaName) == null) { + return escapeDatabaseObject(viewName); + } else { + return escapeDatabaseObject(schemaName)+"."+escapeDatabaseObject(viewName); + } + + } + + } diff --git a/liquibase-core/src/main/java/liquibase/database/core/MySQLDatabase.java b/liquibase-core/src/main/java/liquibase/database/core/MySQLDatabase.java index 8863624916b..13df4c37fcf 100644 --- a/liquibase-core/src/main/java/liquibase/database/core/MySQLDatabase.java +++ b/liquibase-core/src/main/java/liquibase/database/core/MySQLDatabase.java @@ -147,27 +147,6 @@ public String escapeIndexName(String catalogName, String schemaName, String inde return escapeDatabaseObject(indexName); } - - @Override - public String escapeTableName(String catalogName, String schemaName, String tableName) { - return getPrefix(catalogName, schemaName)+tableName; - } - - private String getPrefix(String catalogName, String schemaName) { - String prefix = ""; - if (catalogName != null) { - prefix = catalogName+"."; - } else if (schemaName != null) { - prefix = schemaName + "."; - } - return prefix; - } - - @Override - public String escapeViewName(String catalogName, String schemaName, String viewName) { - return getPrefix(catalogName, schemaName)+viewName; - } - @Override public boolean supportsForeignKeyDisable() { return true; diff --git a/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObjectImpl.java b/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObjectImpl.java index ebf86fedbb6..50f0c7e352d 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObjectImpl.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/DatabaseObjectImpl.java @@ -9,6 +9,9 @@ public boolean equals(DatabaseObject otherObject, Database accordingTo) { } public boolean equals(String otherObjectName, Database accordingTo) { + if (this.getName() == null) { + return otherObjectName == null; + } if (otherObjectName == null) { return false; } diff --git a/liquibase-core/src/main/java/liquibase/database/structure/Schema.java b/liquibase-core/src/main/java/liquibase/database/structure/Schema.java index 3aa6406f765..fe138342b88 100644 --- a/liquibase-core/src/main/java/liquibase/database/structure/Schema.java +++ b/liquibase-core/src/main/java/liquibase/database/structure/Schema.java @@ -26,7 +26,7 @@ public Schema(String catalog, String schemaName) { if (schemaName.equals(Schema.DEFAULT_NAME)) { catalog = Catalog.DEFAULT_NAME; } else { - catalog = schemaName; + catalog = Catalog.DEFAULT_NAME; } } else if (catalog != null && schemaName == null) { if (catalog.equals(Catalog.DEFAULT_NAME)) { diff --git a/liquibase-core/src/main/java/liquibase/datatype/core/NCharType.java b/liquibase-core/src/main/java/liquibase/datatype/core/NCharType.java new file mode 100644 index 00000000000..753cc45c9b1 --- /dev/null +++ b/liquibase-core/src/main/java/liquibase/datatype/core/NCharType.java @@ -0,0 +1,24 @@ +package liquibase.datatype.core; + +import liquibase.database.Database; +import liquibase.database.core.HsqlDatabase; +import liquibase.database.core.OracleDatabase; +import liquibase.datatype.DataTypeInfo; +import liquibase.datatype.DatabaseDataType; +import liquibase.datatype.LiquibaseDataType; + +@DataTypeInfo(name="nchar", aliases = "java.sql.Types.NCHAR", minParameters = 0, maxParameters = 1, priority = LiquibaseDataType.PRIORITY_DEFAULT) +public class NCharType extends CharType { + + @Override + public DatabaseDataType toDatabaseDataType(Database database) { + if (database instanceof HsqlDatabase) { + return new DatabaseDataType("CHAR", getParameters()); + } + if (database instanceof OracleDatabase) { + return new DatabaseDataType("NCHAR2", getParameters()); + } + return super.toDatabaseDataType(database); + } + +} \ No newline at end of file diff --git a/liquibase-core/src/main/java/liquibase/datatype/core/NumericType.java b/liquibase-core/src/main/java/liquibase/datatype/core/NumberType.java similarity index 75% rename from liquibase-core/src/main/java/liquibase/datatype/core/NumericType.java rename to liquibase-core/src/main/java/liquibase/datatype/core/NumberType.java index b3389515370..abd251eaf7c 100644 --- a/liquibase-core/src/main/java/liquibase/datatype/core/NumericType.java +++ b/liquibase-core/src/main/java/liquibase/datatype/core/NumberType.java @@ -1,19 +1,21 @@ -package liquibase.datatype.core; - -import liquibase.database.Database; -import liquibase.database.core.DB2Database; -import liquibase.database.core.MySQLDatabase; -import liquibase.datatype.DataTypeInfo; -import liquibase.datatype.DatabaseDataType; -import liquibase.datatype.LiquibaseDataType; - -@DataTypeInfo(name="number", aliases = {"numeric", "java.sql.Types.NUMERIC"}, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DEFAULT) -public class NumericType extends LiquibaseDataType { - @Override - public DatabaseDataType toDatabaseDataType(Database database) { - if (database instanceof MySQLDatabase || database instanceof DB2Database) { - return new DatabaseDataType("numeric", getParameters()); - } - return super.toDatabaseDataType(database); - } -} +package liquibase.datatype.core; + +import liquibase.database.Database; +import liquibase.database.core.DB2Database; +import liquibase.database.core.HsqlDatabase; +import liquibase.database.core.MSSQLDatabase; +import liquibase.database.core.MySQLDatabase; +import liquibase.datatype.DataTypeInfo; +import liquibase.datatype.DatabaseDataType; +import liquibase.datatype.LiquibaseDataType; + +@DataTypeInfo(name="number", aliases = {"numeric", "java.sql.Types.NUMERIC"}, minParameters = 0, maxParameters = 0, priority = LiquibaseDataType.PRIORITY_DEFAULT) +public class NumberType extends LiquibaseDataType { + @Override + public DatabaseDataType toDatabaseDataType(Database database) { + if (database instanceof MySQLDatabase || database instanceof DB2Database|| database instanceof MSSQLDatabase || database instanceof HsqlDatabase) { + return new DatabaseDataType("numeric", getParameters()); + } + return super.toDatabaseDataType(database); + } +} diff --git a/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java b/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java index 7a6434f1a8e..13eac6b7e38 100644 --- a/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java +++ b/liquibase-core/src/main/java/liquibase/diff/output/DiffToChangeLog.java @@ -330,7 +330,12 @@ protected void addUnexpectedForeignKeyChanges(List changes) { DropForeignKeyConstraintChange change = new DropForeignKeyConstraintChange(); change.setConstraintName(fk.getName()); change.setBaseTableName(fk.getForeignKeyTable().getName()); - change.setBaseTableSchemaName(fk.getForeignKeyTable().getSchema().getName()); + if (diffOutputConfig.isIncludeCatalog()) { + change.setBaseTableCatalogName(fk.getForeignKeyTable().getSchema().getCatalogName()); + } + if (diffOutputConfig.isIncludeSchema()) { + change.setBaseTableSchemaName(fk.getForeignKeyTable().getSchema().getName()); + } changes.add(generateChangeSet(change)); } @@ -343,12 +348,21 @@ protected void addMissingForeignKeyChanges(List changes) { change.setConstraintName(fk.getName()); change.setReferencedTableName(fk.getPrimaryKeyTable().getName()); - change.setReferencedTableSchemaName(fk.getPrimaryKeyTable() - .getSchema().getName()); + if (diffOutputConfig.isIncludeCatalog()) { + change.setReferencedTableCatalogName(fk.getPrimaryKeyTable().getSchema().getCatalogName()); + } + if (diffOutputConfig.isIncludeSchema()) { + change.setReferencedTableSchemaName(fk.getPrimaryKeyTable().getSchema().getName()); + } change.setReferencedColumnNames(fk.getPrimaryKeyColumns()); change.setBaseTableName(fk.getForeignKeyTable().getName()); - change.setBaseTableSchemaName(fk.getForeignKeyTable().getSchema().getName()); + if (diffOutputConfig.isIncludeCatalog()) { + change.setBaseTableCatalogName(fk.getForeignKeyTable().getSchema().getCatalogName()); + } + if (diffOutputConfig.isIncludeSchema()) { + change.setBaseTableSchemaName(fk.getForeignKeyTable().getSchema().getName()); + } change.setBaseColumnNames(fk.getForeignKeyColumns()); change.setDeferrable(fk.isDeferrable()); diff --git a/liquibase-core/src/main/java/liquibase/lockservice/LockService.java b/liquibase-core/src/main/java/liquibase/lockservice/LockService.java index 7ce98cd1d38..4a1b9c94600 100644 --- a/liquibase-core/src/main/java/liquibase/lockservice/LockService.java +++ b/liquibase-core/src/main/java/liquibase/lockservice/LockService.java @@ -140,6 +140,11 @@ public void releaseLock() throws LockException { throw new LockException("Did not update change log lock correctly.\n\n" + updatedRows + " rows were updated instead of the expected 1 row using executor " + executor.getClass().getName()+" there are "+executor.queryForInt(new RawSqlStatement("select count(*) from "+database.getDatabaseChangeLogLockTableName()))+" rows in the table"); } database.commit(); + } + } catch (Exception e) { + throw new LockException(e); + } finally { + try { hasChangeLogLock = false; instances.remove(this.database); @@ -147,11 +152,6 @@ public void releaseLock() throws LockException { database.setCanCacheLiquibaseTableInfo(false); LogFactory.getLogger().info("Successfully released change log lock"); - } - } catch (Exception e) { - throw new LockException(e); - } finally { - try { database.rollback(); } catch (DatabaseException e) { ; diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/DB2DatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/DB2DatabaseSnapshotGenerator.java index 2ffae222816..32f97766339 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/DB2DatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/DB2DatabaseSnapshotGenerator.java @@ -37,4 +37,19 @@ public boolean isColumnAutoIncrement(Database database, Schema schema, String ta return autoIncrement; } + @Override + protected String getJdbcCatalogName(Schema schema) { + return null; + } + + @Override + protected String getJdbcSchemaName(Schema schema) { + return schema.getCatalogName(); + } + + @Override + protected Schema getSchemaFromJdbcInfo(String rawSchemaName, String rawCatalogName, Database database) { + return database.correctSchema(new Schema(rawSchemaName, null)); + } + } diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/H2DatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/H2DatabaseSnapshotGenerator.java index cd5751800f8..b90dcf58309 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/H2DatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/H2DatabaseSnapshotGenerator.java @@ -2,6 +2,7 @@ import liquibase.database.Database; import liquibase.database.structure.Column; +import liquibase.database.structure.Schema; import liquibase.database.structure.Table; import liquibase.database.core.H2Database; import liquibase.exception.DatabaseException; diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/HsqlDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/HsqlDatabaseSnapshotGenerator.java index 0b2c3ccbad4..0c23dae8831 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/HsqlDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/HsqlDatabaseSnapshotGenerator.java @@ -2,6 +2,7 @@ import liquibase.database.Database; import liquibase.database.core.HsqlDatabase; +import liquibase.database.structure.Schema; public class HsqlDatabaseSnapshotGenerator extends JdbcDatabaseSnapshotGenerator { public boolean supports(Database database) { @@ -11,4 +12,10 @@ public boolean supports(Database database) { public int getPriority(Database database) { return PRIORITY_DATABASE; } + + @Override + protected String getJdbcCatalogName(Schema schema) { + return null; + } + } \ No newline at end of file diff --git a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java index aa8ebc4594c..1842ec10a55 100644 --- a/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java +++ b/liquibase-core/src/main/java/liquibase/snapshot/jvm/JdbcDatabaseSnapshotGenerator.java @@ -57,7 +57,7 @@ public boolean hasTable(Schema schema, String tableName, Database database) { tableName = database.correctTableName(tableName); schema = database.correctSchema(schema); } - ResultSet rs = getMetaData(database).getTables(schema.getCatalogName(), schema.getName(), tableName, new String[]{"TABLE"}); + ResultSet rs = getMetaData(database).getTables(getJdbcCatalogName(schema), getJdbcSchemaName(schema), tableName, new String[]{"TABLE"}); try { return rs.next(); } finally { @@ -73,7 +73,7 @@ public boolean hasTable(Schema schema, String tableName, Database database) { public boolean hasView(Schema schema, String viewName, Database database) { try { - ResultSet rs = getMetaData(database).getTables(schema.getCatalogName(), schema.getName(), database.correctTableName(viewName), new String[]{"VIEW"}); + ResultSet rs = getMetaData(database).getTables(getJdbcCatalogName(schema), getJdbcSchemaName(schema), database.correctTableName(viewName), new String[]{"VIEW"}); try { return rs.next(); } finally { @@ -91,7 +91,7 @@ public Table getTable(Schema schema, String tableName, Database database) throws ResultSet rs = null; try { DatabaseMetaData metaData = getMetaData(database); - rs = metaData.getTables(schema.getCatalogName(), schema.getName(), database.correctTableName(tableName), new String[]{"TABLE"}); + rs = metaData.getTables(getJdbcCatalogName(schema), getJdbcSchemaName(schema), database.correctTableName(tableName), new String[]{"TABLE"}); Table table; try { @@ -144,7 +144,7 @@ public boolean hasPrimaryKey(Schema schema, String tableName, String primaryKeyN public Column getColumn(Schema schema, String tableName, String columnName, Database database) throws DatabaseException { ResultSet rs = null; try { - rs = getMetaData(database).getColumns(schema.getCatalogName(), schema.getName(), database.correctTableName(tableName), database.correctColumnName(columnName)); + rs = getMetaData(database).getColumns(getJdbcCatalogName(schema), getJdbcSchemaName(schema), database.correctTableName(tableName), database.correctColumnName(columnName)); if (!rs.next()) { return null; @@ -177,10 +177,11 @@ protected Table readTable(ResultSet tableMetadataResultSet, Database database, b table.setRawSchemaName(rawSchemaName); table.setRawCatalogName(rawCatalogName); - table.setSchema(database.correctSchema(new Schema(rawCatalogName, rawSchemaName))); + table.setSchema(getSchemaFromJdbcInfo(rawSchemaName, rawCatalogName, database)); if (readColumns) { - ResultSet columnMetadataResultSet = getMetaData(database).getColumns(table.getRawCatalogName(), table.getRawSchemaName(), rawTableName, null); + Schema rawSchema = database.correctSchema(new Schema(table.getRawCatalogName(), table.getRawSchemaName())); + ResultSet columnMetadataResultSet = getMetaData(database).getColumns(getJdbcCatalogName(rawSchema), getJdbcSchemaName(rawSchema), rawTableName, null); try { while (columnMetadataResultSet.next()) { table.getColumns().add(readColumn(convertResultSetToMap(columnMetadataResultSet), table, database)); @@ -193,6 +194,10 @@ protected Table readTable(ResultSet tableMetadataResultSet, Database database, b return table; } + protected Schema getSchemaFromJdbcInfo(String rawSchemaName, String rawCatalogName, Database database) { + return database.correctSchema(new Schema(rawCatalogName, rawSchemaName)); + } + protected View readView(ResultSet viewMetadataResultSet, Database database) throws SQLException, DatabaseException { String rawViewName = viewMetadataResultSet.getString("TABLE_NAME"); String rawSchemaName = StringUtils.trimToNull(viewMetadataResultSet.getString("TABLE_SCHEM")); @@ -205,7 +210,7 @@ protected View readView(ResultSet viewMetadataResultSet, Database database) thro view.setRawSchemaName(rawSchemaName); view.setRawCatalogName(rawCatalogName); - view.setSchema(database.correctSchema(new Schema(rawCatalogName, rawSchemaName))); + view.setSchema(getSchemaFromJdbcInfo(rawSchemaName, rawCatalogName, database)); try { view.setDefinition(database.getViewDefinition(view.getSchema(), view.getName())); @@ -243,36 +248,38 @@ protected Column readColumn(Map columnMetadataResultSet, Relatio column.setNullable(true); } - if (columnMetadataResultSet.containsKey("IS_AUTOINCREMENT")) { - String isAutoincrement = (String) columnMetadataResultSet.get("IS_AUTOINCREMENT"); - if (isAutoincrement.equals("YES")) { - column.setAutoIncrement(true); - } else if (isAutoincrement.equals("NO")) { - column.setAutoIncrement(false); - } else if (isAutoincrement.equals("")) { - LogFactory.getLogger().info("Unknown auto increment state for column " + column.toString() + ". Assuming not auto increment"); - column.setAutoIncrement(false); - } else { - throw new UnexpectedLiquibaseException("Unknown is_autoincrement value: " + isAutoincrement); - } - } else { - //probably older version of java, need to select from the column to find out if it is auto-increment - String selectStatement = "select " + database.escapeColumnName(rawCatalogName, rawSchemaName, rawTableName, rawColumnName) + " from " + database.escapeTableName(rawCatalogName, rawSchemaName, rawTableName) + " where 0=1"; - Connection underlyingConnection = ((JdbcConnection) database.getConnection()).getUnderlyingConnection(); - Statement statement = underlyingConnection.createStatement(); - ResultSet columnSelectRS = statement.executeQuery(selectStatement); - try { - if (columnSelectRS.getMetaData().isAutoIncrement(1)) { + if (table instanceof Table) { + if (columnMetadataResultSet.containsKey("IS_AUTOINCREMENT")) { + String isAutoincrement = (String) columnMetadataResultSet.get("IS_AUTOINCREMENT"); + if (isAutoincrement.equals("YES")) { column.setAutoIncrement(true); - } else { + } else if (isAutoincrement.equals("NO")) { column.setAutoIncrement(false); + } else if (isAutoincrement.equals("")) { + LogFactory.getLogger().info("Unknown auto increment state for column " + column.toString() + ". Assuming not auto increment"); + column.setAutoIncrement(false); + } else { + throw new UnexpectedLiquibaseException("Unknown is_autoincrement value: " + isAutoincrement); } - } finally { + } else { + //probably older version of java, need to select from the column to find out if it is auto-increment + String selectStatement = "select " + database.escapeColumnName(rawCatalogName, rawSchemaName, rawTableName, rawColumnName) + " from " + database.escapeTableName(rawCatalogName, rawSchemaName, rawTableName) + " where 0=1"; + Connection underlyingConnection = ((JdbcConnection) database.getConnection()).getUnderlyingConnection(); + Statement statement = underlyingConnection.createStatement(); + ResultSet columnSelectRS = statement.executeQuery(selectStatement); try { - statement.close(); - } catch (SQLException ignore) { + if (columnSelectRS.getMetaData().isAutoIncrement(1)) { + column.setAutoIncrement(true); + } else { + column.setAutoIncrement(false); + } + } finally { + try { + statement.close(); + } catch (SQLException ignore) { + } + columnSelectRS.close(); } - columnSelectRS.close(); } } @@ -352,7 +359,7 @@ protected void readTables(DatabaseSnapshot snapshot, Schema schema, DatabaseMeta Database database = snapshot.getDatabase(); updateListeners("Reading tables for " + database.toString() + " ..."); - ResultSet tableMetaDataRs = databaseMetaData.getTables(schema.getCatalogName(), schema.getName(), null, new String[]{"TABLE", "ALIAS"}); + ResultSet tableMetaDataRs = databaseMetaData.getTables(getJdbcCatalogName(schema), getJdbcSchemaName(schema), null, new String[]{"TABLE", "ALIAS"}); try { while (tableMetaDataRs.next()) { Table table = readTable(tableMetaDataRs, database, false); @@ -385,7 +392,7 @@ protected void readViews(DatabaseSnapshot snapshot, Schema schema, DatabaseMetaD Database database = snapshot.getDatabase(); updateListeners("Reading views for " + database.toString() + " ..."); - ResultSet viewsMetadataRs = databaseMetaData.getTables(schema.getCatalogName(), schema.getName(), null, new String[]{"VIEW"}); + ResultSet viewsMetadataRs = databaseMetaData.getTables(getJdbcCatalogName(schema), getJdbcSchemaName(schema), null, new String[]{"VIEW"}); try { while (viewsMetadataRs.next()) { View view = readView(viewsMetadataRs, database); @@ -416,7 +423,7 @@ protected void readColumns(DatabaseSnapshot snapshot, Schema schema, DatabaseMet ResultSet allColumnsMetadataRs = null; try { - allColumnsMetadataRs = databaseMetaData.getColumns(schema.getCatalogName(), schema.getName(), null, null); + allColumnsMetadataRs = databaseMetaData.getColumns(getJdbcCatalogName(schema), getJdbcSchemaName(schema), null, null); while (allColumnsMetadataRs.next()) { Map data = convertResultSetToMap(allColumnsMetadataRs); String tableOrViewName = cleanObjectNameFromDatabase((String) data.get("TABLE_NAME")); @@ -454,7 +461,7 @@ protected void readColumns(DatabaseSnapshot snapshot, Schema schema, DatabaseMet } private Map convertResultSetToMap(ResultSet rs) throws SQLException { - Class[] types = new Class[]{ //matches tableMetadata.getColumns() types. UglY, but otherwise get wrong types + Class[] types = new Class[]{ //matches tableMetadata.getColumns() types. Ugly, but otherwise get wrong types null, //no zero index String.class, String.class, @@ -615,7 +622,8 @@ protected void readForeignKeys(DatabaseSnapshot snapshot, Schema schema, Databas // Then tries to find all other standard FKs for (Table table : snapshot.getDatabaseObjects(schema, Table.class)) { - ResultSet importedKeyMetadataResultSet = getMetaData(database).getImportedKeys(table.getRawCatalogName(), table.getRawSchemaName(), table.getName()); + Schema rawSchema = getSchemaFromJdbcInfo(table.getRawSchemaName(), table.getRawCatalogName(), database); + ResultSet importedKeyMetadataResultSet = getMetaData(database).getImportedKeys(getJdbcCatalogName(rawSchema), getJdbcSchemaName(rawSchema), table.getName()); try { while (importedKeyMetadataResultSet.next()) { @@ -652,11 +660,14 @@ protected void readForeignKeys(DatabaseSnapshot snapshot, Schema schema, Databas public boolean hasIndex(Schema schema, String tableName, String indexName, String columnNames, Database database) throws DatabaseException { try { if (tableName == null) { - ResultSet rs = getMetaData(database).getTables(schema.getCatalogName(), schema.getName(), null, new String[]{"TABLE"}); + ResultSet rs = getMetaData(database).getTables(getJdbcCatalogName(schema), getJdbcSchemaName(schema), null, new String[]{"TABLE"}); try { while (rs.next()) { - if (hasIndex(schema, rs.getString("TABLE_NAME"), indexName, columnNames, database)) { - return true; + String foundTable = rs.getString("TABLE_NAME"); + if (!database.isSystemTable(schema, foundTable) && !database.isSystemView(schema, foundTable)) { + if (hasIndex(schema, foundTable, indexName, columnNames, database)) { + return true; + } } } return false; @@ -676,7 +687,7 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin if (columnNames != null) { Map> columnsByIndexName = new HashMap>(); - ResultSet rs = getMetaData(database).getIndexInfo(schema.getCatalogName(), schema.getName(), database.correctTableName(tableName), false, true); + ResultSet rs = getMetaData(database).getIndexInfo(getJdbcCatalogName(schema), getJdbcSchemaName(schema), database.correctTableName(tableName), false, true); try { while (rs.next()) { String foundIndexName = rs.getString("INDEX_NAME"); @@ -709,7 +720,7 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin rs.close(); } } else if (indexName != null) { - ResultSet rs = getMetaData(database).getIndexInfo(schema.getCatalogName(), schema.getName(), database.correctTableName(tableName), false, true); + ResultSet rs = getMetaData(database).getIndexInfo(getJdbcCatalogName(schema), getJdbcSchemaName(schema), database.correctTableName(tableName), false, true); try { while (rs.next()) { Index foundIndex = new Index() @@ -740,7 +751,7 @@ public boolean hasIndex(Schema schema, String tableName, String indexName, Strin public boolean hasForeignKey(Schema schema, String foreignKeyTableName, String fkName, Database database) throws DatabaseException { ForeignKey fk = new ForeignKey().setName(fkName); try { - ResultSet rs = getMetaData(database).getImportedKeys(schema.getCatalogName(), schema.getName(), database.correctTableName(foreignKeyTableName)); + ResultSet rs = getMetaData(database).getImportedKeys(getJdbcCatalogName(schema), getJdbcSchemaName(schema), database.correctTableName(foreignKeyTableName)); try { while (rs.next()) { ForeignKey foundFk = new ForeignKey().setName(rs.getString("FK_NAME")); @@ -854,7 +865,7 @@ protected void readIndexes(DatabaseSnapshot snapshot, Schema schema, DatabaseMet String sql = "SELECT INDEX_NAME, 3 AS TYPE, TABLE_NAME, COLUMN_NAME, COLUMN_POSITION AS ORDINAL_POSITION, null AS FILTER_CONDITION FROM ALL_IND_COLUMNS WHERE TABLE_OWNER='" + schema.getName() + "' AND TABLE_NAME='" + table.getName() + "' ORDER BY INDEX_NAME, ORDINAL_POSITION"; rs = statement.executeQuery(sql); } else { - rs = databaseMetaData.getIndexInfo(schema.getCatalogName(), schema.getName(), table.getName(), false, true); + rs = databaseMetaData.getIndexInfo(getJdbcCatalogName(schema), getJdbcSchemaName(schema), table.getName(), false, true); } Map indexMap = new HashMap(); while (rs.next()) { @@ -987,7 +998,7 @@ protected void readPrimaryKeys(DatabaseSnapshot snapshot, Schema schema, Databas List foundPKs = new ArrayList(); for (Table table : snapshot.getDatabaseObjects(schema, Table.class)) { - ResultSet rs = databaseMetaData.getPrimaryKeys(schema.getCatalogName(), schema.getName(), table.getName()); + ResultSet rs = databaseMetaData.getPrimaryKeys(getJdbcCatalogName(schema), getJdbcSchemaName(schema), table.getName()); try { while (rs.next()) { @@ -1123,4 +1134,12 @@ public DateFormat getTimeFormat() { public DateFormat getDateTimeFormat() { return new SimpleDateFormat("yyyy-MM-dd HH:mm:SS.S"); } + + protected String getJdbcCatalogName(Schema schema) { + return schema.getCatalogName(); + } + + protected String getJdbcSchemaName(Schema schema) { + return schema.getName(); + } } diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/AddColumnGenerator.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/AddColumnGenerator.java index bfbc85feeee..d43c3bde8b3 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/AddColumnGenerator.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/AddColumnGenerator.java @@ -50,7 +50,7 @@ public ValidationErrors validate(AddColumnStatement statement, Database database public Sql[] generateSql(AddColumnStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { - String alterTable = "ALTER TABLE " + database.escapeTableName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName()) + " ADD " + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " " + DataTypeFactory.getInstance().fromDescription(statement.getColumnType() + (statement.isAutoIncrement() ? "{autoIncrement:true}" : "")); + String alterTable = "ALTER TABLE " + database.escapeTableName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName()) + " ADD " + database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), statement.getColumnName()) + " " + DataTypeFactory.getInstance().fromDescription(statement.getColumnType() + (statement.isAutoIncrement() ? "{autoIncrement:true}" : "")).toDatabaseDataType(database); if (statement.isAutoIncrement() && database.supportsAutoIncrement()) { AutoIncrementConstraint autoIncrementConstraint = statement.getAutoIncrementConstraint(); diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateTableGenerator.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateTableGenerator.java index ddeeb5a7b3d..1e2713a62a9 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateTableGenerator.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateTableGenerator.java @@ -40,7 +40,7 @@ public Sql[] generateSql(CreateTableStatement statement, Database database, SqlG buffer.append(database.escapeColumnName(statement.getCatalogName(), statement.getSchemaName(), statement.getTableName(), column)); buffer.append(" ").append(statement.getColumnTypes().get(column).toDatabaseDataType(database)); - + AutoIncrementConstraint autoIncrementConstraint = null; for (AutoIncrementConstraint currentAutoIncrementConstraint : statement.getAutoIncrementConstraints()) { diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateViewGenerator.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateViewGenerator.java index 3af4dd2c798..b968c3fe28d 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateViewGenerator.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/CreateViewGenerator.java @@ -2,6 +2,7 @@ import liquibase.database.Database; import liquibase.database.core.*; +import liquibase.database.structure.Schema; import liquibase.exception.ValidationErrors; import liquibase.sql.Sql; import liquibase.sql.UnparsedSql; @@ -46,8 +47,9 @@ public Sql[] generateSql(CreateViewStatement statement, Database database, SqlGe } else if (database instanceof MSSQLDatabase) { if (statement.isReplaceIfExists()) { //from http://stackoverflow.com/questions/163246/sql-server-equivalent-to-oracles-create-or-replace-view - sql.add(new UnparsedSql("IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'["+statement.getSchemaName()+"].["+statement.getViewName()+"]'))\n" + - " EXEC sp_executesql N'CREATE VIEW ["+statement.getSchemaName()+"].["+statement.getViewName()+"] AS SELECT ''This is a code stub which will be replaced by an Alter Statement'' as [code_stub]'")); + Schema schema = database.correctSchema(new Schema(statement.getCatalogName(), statement.getSchemaName())); + sql.add(new UnparsedSql("IF NOT EXISTS (SELECT * FROM sys.views WHERE object_id = OBJECT_ID(N'["+ schema.getName() +"].["+statement.getViewName()+"]'))\n" + + " EXEC sp_executesql N'CREATE VIEW ["+schema.getName()+"].["+statement.getViewName()+"] AS SELECT ''This is a code stub which will be replaced by an Alter Statement'' as [code_stub]'")); createClause = "ALTER VIEW"; } else { createClause = "CREATE VIEW"; @@ -55,9 +57,8 @@ public Sql[] generateSql(CreateViewStatement statement, Database database, SqlGe } else { createClause = "CREATE " + (statement.isReplaceIfExists() ? "OR REPLACE " : "") + "VIEW"; } + sql.add(new UnparsedSql(createClause + " " + database.escapeViewName(statement.getCatalogName(), statement.getSchemaName(), statement.getViewName()) + " AS " + statement.getSelectQuery())); - return new Sql[]{ - new UnparsedSql(createClause + " " + database.escapeViewName(statement.getCatalogName(), statement.getSchemaName(), statement.getViewName()) + " AS " + statement.getSelectQuery()) - }; + return sql.toArray(new Sql[sql.size()]); } } diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGenerator.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGenerator.java index dcc7b1f03d0..c8e9b95ecd7 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGenerator.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGenerator.java @@ -1,6 +1,7 @@ package liquibase.sqlgenerator.core; import liquibase.database.Database; +import liquibase.database.core.MySQLDatabase; import liquibase.database.structure.Schema; import liquibase.exception.DatabaseException; import liquibase.exception.UnexpectedLiquibaseException; @@ -22,14 +23,26 @@ public ValidationErrors validate(GetViewDefinitionStatement getViewDefinitionSta public Sql[] generateSql(GetViewDefinitionStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { Schema schema = database.correctSchema(new Schema(statement.getCatalogName(), statement.getSchemaName())); - String sql = "select view_definition from information_schema.views where upper(table_name)='" + statement.getViewName().toUpperCase() + "'"; - - if (statement.getSchemaName() != null) { - sql += " and table_schema='" + schema.getName() + "'"; - } - - if (statement.getCatalogName() != null) { - sql += " and table_catalog='" + schema.getCatalogName() + "'"; + String sql = "select view_definition from information_schema.views where table_name='" + database.correctTableName(statement.getViewName()) + "'"; + + if (database instanceof MySQLDatabase) { + String catalogName = database.getAssumedCatalogName(schema.getCatalogName(), schema.getName()); + sql += " and table_schema='" + catalogName + "'"; + } else { + + if (database.supportsSchemas()) { + String schemaName = database.getAssumedSchemaName(schema.getCatalogName(), schema.getName()); + if (schemaName != null) { + sql += " and table_schema='" + schemaName + "'"; + } + } + + if (database.supportsCatalogs()) { + String catalogName = database.getAssumedCatalogName(schema.getCatalogName(), schema.getName()); + if (catalogName != null) { + sql += " and table_catalog='" + catalogName + "'"; + } + } } return new Sql[]{ diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorDB2.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorDB2.java index a207ff639ae..f3c673dfb6f 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorDB2.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorDB2.java @@ -27,7 +27,7 @@ public Sql[] generateSql(GetViewDefinitionStatement statement, Database database Schema schema = database.correctSchema(new Schema(statement.getCatalogName(), statement.getSchemaName())); return new Sql[] { - new UnparsedSql("select view_definition from SYSIBM.VIEWS where TABLE_NAME='" + statement.getViewName() + "' and TABLE_SCHEMA='" + schema.getName() + "'") + new UnparsedSql("select view_definition from SYSIBM.VIEWS where TABLE_NAME='" + statement.getViewName() + "' and TABLE_SCHEMA='" + database.getAssumedCatalogName(schema.getCatalogName(), schema.getName()) + "'") }; } } diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorHsql.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorHsql.java index 5f77579336d..9b6806e635d 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorHsql.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorHsql.java @@ -27,7 +27,7 @@ public Sql[] generateSql(GetViewDefinitionStatement statement, Database database Schema schema = database.correctSchema(new Schema(statement.getCatalogName(), statement.getSchemaName())); return new Sql[] { - new UnparsedSql("SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.SYSTEM_VIEWS WHERE TABLE_NAME = '" + statement.getViewName() + "' AND TABLE_SCHEMA='" + schema.getSchema() + "'") + new UnparsedSql("SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.SYSTEM_VIEWS WHERE TABLE_NAME = '" + statement.getViewName() + "' AND TABLE_SCHEMA='" + schema.getName() + "'") }; } } \ No newline at end of file diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorInformationSchemaViews.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorInformationSchemaViews.java deleted file mode 100644 index b0cad23eecd..00000000000 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/GetViewDefinitionGeneratorInformationSchemaViews.java +++ /dev/null @@ -1,33 +0,0 @@ -package liquibase.sqlgenerator.core; - -import liquibase.database.Database; -import liquibase.database.core.H2Database; -import liquibase.database.core.MySQLDatabase; -import liquibase.database.structure.Schema; -import liquibase.exception.DatabaseException; -import liquibase.exception.UnexpectedLiquibaseException; -import liquibase.sql.Sql; -import liquibase.sql.UnparsedSql; -import liquibase.sqlgenerator.SqlGeneratorChain; -import liquibase.statement.core.GetViewDefinitionStatement; - -public class GetViewDefinitionGeneratorInformationSchemaViews extends GetViewDefinitionGenerator { - @Override - public int getPriority() { - return PRIORITY_DATABASE; - } - - @Override - public boolean supports(GetViewDefinitionStatement statement, Database database) { - return database instanceof H2Database || database instanceof MySQLDatabase; - } - - @Override - public Sql[] generateSql(GetViewDefinitionStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { - Schema schema = database.correctSchema(new Schema(statement.getCatalogName(), statement.getSchemaName())); - - return new Sql[]{ - new UnparsedSql("SELECT VIEW_DEFINITION FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_NAME = '" + statement.getViewName() + "' AND TABLE_SCHEMA='" + schema.getName() + "'") - }; - } -} \ No newline at end of file diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/SelectSequencesGeneratorDB2.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/SelectSequencesGeneratorDB2.java index d2eeb8b6a8d..4d62388498b 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/SelectSequencesGeneratorDB2.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/SelectSequencesGeneratorDB2.java @@ -31,7 +31,7 @@ public Sql[] generateSql(SelectSequencesStatement statement, Database database, Schema schema = database.correctSchema(new Schema(statement.getCatalogName(), statement.getSchemaName())); return new Sql[] { - new UnparsedSql("SELECT SEQNAME AS SEQUENCE_NAME FROM SYSCAT.SEQUENCES WHERE SEQTYPE='S' AND SEQSCHEMA = '" + schema.getName() + "'") + new UnparsedSql("SELECT SEQNAME AS SEQUENCE_NAME FROM SYSCAT.SEQUENCES WHERE SEQTYPE='S' AND SEQSCHEMA = '" + schema.getCatalogName() + "'") }; } } diff --git a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/StoredProcedureGenerator.java b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/StoredProcedureGenerator.java index f70d4b291a4..f3a832536cc 100644 --- a/liquibase-core/src/main/java/liquibase/sqlgenerator/core/StoredProcedureGenerator.java +++ b/liquibase-core/src/main/java/liquibase/sqlgenerator/core/StoredProcedureGenerator.java @@ -1,6 +1,7 @@ package liquibase.sqlgenerator.core; import liquibase.database.Database; +import liquibase.database.core.OracleDatabase; import liquibase.exception.ValidationErrors; import liquibase.sql.Sql; import liquibase.sql.UnparsedSql; @@ -17,12 +18,17 @@ public ValidationErrors validate(StoredProcedureStatement storedProcedureStateme } public Sql[] generateSql(StoredProcedureStatement statement, Database database, SqlGeneratorChain sqlGeneratorChain) { - StringBuffer string = new StringBuffer(); - string.append("exec (").append(statement.getProcedureName()); + StringBuilder string = new StringBuilder(); + string.append("exec ").append(statement.getProcedureName()).append("("); for (String param : statement.getParameters()) { string.append(" ").append(param).append(","); } - return new Sql[] { new UnparsedSql(string.toString().replaceFirst(",$", ")") )}; + String sql = string.toString().replaceFirst(",$", "")+")"; + + if (database instanceof OracleDatabase) { + sql = sql.replaceFirst("exec ", "BEGIN ").replaceFirst("\\)$", "); END;"); + } + return new Sql[] { new UnparsedSql(sql)}; } } diff --git a/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java b/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java index c73caf2f9d2..7659836a3d0 100644 --- a/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java +++ b/liquibase-core/src/test/java/liquibase/database/core/MockDatabase.java @@ -529,4 +529,20 @@ public String correctForeignKeyName(String fkName) { public String correctIndexName(String indexName) { return indexName; } + + public String escapeSchemaName(String schemaName) { + return schemaName; + } + + public String escapeCatalogName(String name) { + return name; + } + + public String getAssumedSchemaName(String catalogName, String schemaName) { + return schemaName; + } + + public String getAssumedCatalogName(String catalogName, String schemaName) { + return catalogName; + } } diff --git a/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java b/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java index 042278c6ff0..99a31f633e4 100644 --- a/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java +++ b/liquibase-integration-tests/src/test/java/liquibase/dbtest/AbstractIntegrationTest.java @@ -120,10 +120,17 @@ public void setUp() throws Exception { DatabaseSnapshotGeneratorFactory.resetAll(); LockService.getInstance(database).forceReleaseLock(); database.dropDatabaseObjects(Schema.DEFAULT); + if (database.supportsSchemas()) { - database.dropDatabaseObjects(new Schema(DatabaseTestContext.ALT_CATALOG, DatabaseTestContext.ALT_SCHEMA)); - } else if (database.supportsCatalogs()) { - database.dropDatabaseObjects(new Schema(DatabaseTestContext.ALT_SCHEMA, null)); + database.dropDatabaseObjects(new Schema((String) null, DatabaseTestContext.ALT_SCHEMA)); + } + + if (supportsAltCatalogTests()) { + if (database.supportsSchemas() && database.supportsCatalogs()) { + database.dropDatabaseObjects(new Schema(DatabaseTestContext.ALT_CATALOG, DatabaseTestContext.ALT_SCHEMA)); + } else if (database.supportsCatalogs()) { + database.dropDatabaseObjects(new Schema((String) null, DatabaseTestContext.ALT_SCHEMA)); + } } database.commit(); DatabaseSnapshotGeneratorFactory.resetAll(); @@ -131,6 +138,10 @@ public void setUp() throws Exception { } } + protected boolean supportsAltCatalogTests() { + return database.supportsCatalogs(); + } + protected Properties createProperties() { return new Properties(); } diff --git a/liquibase-integration-tests/src/test/java/liquibase/dbtest/hsqldb/HsqlIntegrationTest.java b/liquibase-integration-tests/src/test/java/liquibase/dbtest/hsqldb/HsqlIntegrationTest.java index a426d3b1a9b..9de61b8d19d 100644 --- a/liquibase-integration-tests/src/test/java/liquibase/dbtest/hsqldb/HsqlIntegrationTest.java +++ b/liquibase-integration-tests/src/test/java/liquibase/dbtest/hsqldb/HsqlIntegrationTest.java @@ -9,14 +9,4 @@ public class HsqlIntegrationTest extends AbstractIntegrationTest { public HsqlIntegrationTest() throws Exception { super("hsqldb", "jdbc:hsqldb:mem:liquibase"); } - - - /** - * We expect a DatabaseException because HSQLDB 1.8 doesn't support fks beetween schemas.
- */ - @Override - @Test(expected=MigrationFailedException.class) - public void testDiffExternalForeignKeys() throws Exception { - super.testDiffExternalForeignKeys(); - } } diff --git a/liquibase-integration-tests/src/test/java/liquibase/dbtest/mssql/MssqlIntegrationTest.java b/liquibase-integration-tests/src/test/java/liquibase/dbtest/mssql/MssqlIntegrationTest.java index aca51f47609..3cbcbfa08c9 100644 --- a/liquibase-integration-tests/src/test/java/liquibase/dbtest/mssql/MssqlIntegrationTest.java +++ b/liquibase-integration-tests/src/test/java/liquibase/dbtest/mssql/MssqlIntegrationTest.java @@ -4,5 +4,10 @@ public class MssqlIntegrationTest extends AbstractMssqlIntegrationTest { public MssqlIntegrationTest() throws Exception { super("Mssql", "jdbc:sqlserver://"+ getDatabaseServerHostname("Mssql") +":1433;databaseName=liquibase"); - } + } + + @Override + protected boolean supportsAltCatalogTests() { + return false; + } } diff --git a/liquibase-integration-tests/src/test/resources/changelogs/oracle/rollback/rollbackable.changelog.xml b/liquibase-integration-tests/src/test/resources/changelogs/oracle/rollback/rollbackable.changelog.xml index 270e97c90f5..7a6e97fa463 100644 --- a/liquibase-integration-tests/src/test/resources/changelogs/oracle/rollback/rollbackable.changelog.xml +++ b/liquibase-integration-tests/src/test/resources/changelogs/oracle/rollback/rollbackable.changelog.xml @@ -107,7 +107,7 @@ + newTableName="isbn" newColumnName="code" newColumnDataType="varchar(50)"/>