Author: tomdz Date: Sun Mar 9 05:35:44 2008 New Revision: 635228 URL: http://svn.apache.org/viewvc?rev=635228&view=rev Log: Added support for specification of which tables to remove (DDLUTILS-180, DDLUTILS-87)
Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveTablesChange.java Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/task/DropTablesCommand.java db/ddlutils/trunk/src/test/org/apache/ddlutils/TestDatabaseWriterBase.java db/ddlutils/trunk/src/test/org/apache/ddlutils/io/RoundtripTestBase.java db/ddlutils/trunk/src/test/org/apache/ddlutils/task/TestDropTablesCommand.java Added: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveTablesChange.java URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveTablesChange.java?rev=635228&view=auto ============================================================================== --- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveTablesChange.java (added) +++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/RemoveTablesChange.java Sun Mar 9 05:35:44 2008 @@ -0,0 +1,131 @@ +package org.apache.ddlutils.alteration; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.regex.Pattern; + +import org.apache.ddlutils.model.Database; +import org.apache.ddlutils.model.ForeignKey; +import org.apache.ddlutils.model.Table; + +/** + * Represents the removal of tables and foreign keys to them, from a model. + * + * @version $Revision: $ + */ +public class RemoveTablesChange implements ModelChange +{ + /** The names of the tables to be removed. */ + private String[] _tableNames; + /** The regular expression matching the names of the tables to be removed. */ + private Pattern _tableNameRegExp; + + /** + * Creates a new change object. + * + * @param tableNames The names of the tables to be removed + */ + public RemoveTablesChange(String[] tableNames) + { + _tableNames = new String[tableNames.length]; + System.arraycopy(tableNames, 0, _tableNames, 0, tableNames.length); + } + + /** + * Creates a new change object. + * + * @param tableNameRegExp The regular expression matching the names of the tables + * to be removed (see [EMAIL PROTECTED] java.util.regex.Pattern} + * for details); for case insensitive matching, an uppercase + * name can be assumed + */ + public RemoveTablesChange(String tableNameRegExp) + { + _tableNameRegExp = Pattern.compile(tableNameRegExp); + } + + /** + * [EMAIL PROTECTED] + */ + public void apply(Database model, boolean caseSensitive) + { + ArrayList tables = new ArrayList(); + + if (_tableNames != null) + { + for (int idx = 0; idx < _tableNames.length; idx++) + { + Table table = model.findTable(_tableNames[idx], caseSensitive); + + if (table != null) + { + tables.add(table); + } + } + } + else if (_tableNameRegExp != null) + { + for (int idx = 0; idx < model.getTableCount(); idx++) + { + Table table = model.getTable(idx); + String tableName = table.getName(); + + if (!caseSensitive) + { + tableName = tableName.toUpperCase(); + } + if (_tableNameRegExp.matcher(tableName).matches()) + { + tables.add(table); + } + } + } + for (Iterator tableIt = tables.iterator(); tableIt.hasNext();) + { + Table targetTable = (Table)tableIt.next(); + + for (int tableIdx = 0; tableIdx < model.getTableCount(); tableIdx++) + { + Table curTable = model.getTable(tableIdx); + ArrayList fksToRemove = new ArrayList(); + + for (int fkIdx = 0; fkIdx < curTable.getForeignKeyCount(); fkIdx++) + { + ForeignKey curFk = curTable.getForeignKey(fkIdx); + + if (curFk.getForeignTable().equals(targetTable)) + { + fksToRemove.add(curFk); + } + } + for (Iterator fkIt = fksToRemove.iterator(); fkIt.hasNext();) + { + curTable.removeForeignKey((ForeignKey)fkIt.next()); + } + } + } + for (Iterator tableIt = tables.iterator(); tableIt.hasNext();) + { + model.removeTable((Table)tableIt.next()); + } + } +} Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/task/DropTablesCommand.java URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/java/org/apache/ddlutils/task/DropTablesCommand.java?rev=635228&r1=635227&r2=635228&view=diff ============================================================================== --- db/ddlutils/trunk/src/java/org/apache/ddlutils/task/DropTablesCommand.java (original) +++ db/ddlutils/trunk/src/java/org/apache/ddlutils/task/DropTablesCommand.java Sun Mar 9 05:35:44 2008 @@ -19,8 +19,12 @@ * under the License. */ +import java.util.ArrayList; + import org.apache.commons.dbcp.BasicDataSource; import org.apache.ddlutils.Platform; +import org.apache.ddlutils.alteration.RemoveTablesChange; +import org.apache.ddlutils.model.CloneHelper; import org.apache.ddlutils.model.Database; import org.apache.tools.ant.BuildException; @@ -32,6 +36,73 @@ */ public class DropTablesCommand extends DatabaseCommand { + /** The names of the tables to be dropped. */ + private String[] _tableNames; + /** The regular expression matching the names of the tables to be dropped. */ + private String _tableNameRegExp; + + /** + * Sets the names of the tables to be removed, as a comma-separated list. Escape a + * comma via '\,' if it is part of the table name. Please note that table names are + * not trimmed which means that whitespace characters should only be present in + * this string if they are actually part of the table name (i.e. in delimited + * identifer mode). + * + * @param tableNameList The comma-separated list of table names + * @ant.not-required If no table filter is specified, then all tables will be dropped. + */ + public void setTableNames(String tableNameList) + { + String[] tmpTableNames = tableNameList.split(","); + ArrayList tableNames = new ArrayList(); + String last = null; + + for (int idx = 0; idx < tmpTableNames.length; idx++) + { + String str = tmpTableNames[idx]; + int strLen = str.length(); + boolean endsInSlash = (strLen > 0) && (str.charAt(strLen - 1) == '\\') && + ((strLen == 1) || (str.charAt(strLen - 2) != '\\')); + + if (last != null) + { + last += "," + str; + if (!endsInSlash) + { + tableNames.add(last); + last = null; + } + } + else if (endsInSlash) + { + last = str.substring(0, strLen - 1); + } + else + { + tableNames.add(str); + } + } + if (last != null) + { + tableNames.add(last + ","); + } + _tableNames = (String[])tableNames.toArray(new String[tableNames.size()]); + } + + /** + * Sets the regular expression matching the names of the tables to be removed. + * For case insensitive matching, an uppercase name can be assumed. If no + * regular expressionis specified + * + * @param tableNameRegExp The regular expression; see [EMAIL PROTECTED] java.util.regex.Pattern} + * for details + * @ant.not-required If no table filter is specified, then all tables will be dropped. + */ + public void setTableNameRegExp(String tableNameRegExp) + { + _tableNameRegExp = tableNameRegExp; + } + /** * [EMAIL PROTECTED] */ @@ -55,6 +126,15 @@ Platform platform = getPlatform(); Database targetModel = new Database(); + if ((_tableNames != null) || (_tableNameRegExp != null)) + { + RemoveTablesChange change = _tableNames != null ? new RemoveTablesChange(_tableNames) + : new RemoveTablesChange(_tableNameRegExp); + + targetModel = new CloneHelper().clone(model); + targetModel.initialize(); + change.apply(targetModel, task.isUseDelimitedSqlIdentifiers()); + } try { platform.alterModel(model, targetModel, isFailOnError()); Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/TestDatabaseWriterBase.java URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/TestDatabaseWriterBase.java?rev=635228&r1=635227&r2=635228&view=diff ============================================================================== --- db/ddlutils/trunk/src/test/org/apache/ddlutils/TestDatabaseWriterBase.java (original) +++ db/ddlutils/trunk/src/test/org/apache/ddlutils/TestDatabaseWriterBase.java Sun Mar 9 05:35:44 2008 @@ -26,6 +26,7 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.Statement; +import java.sql.Types; import java.util.ArrayList; import java.util.Iterator; import java.util.List; @@ -42,8 +43,13 @@ import org.apache.commons.dbcp.BasicDataSource; import org.apache.ddlutils.io.DataReader; import org.apache.ddlutils.io.DataToDatabaseSink; +import org.apache.ddlutils.model.CloneHelper; +import org.apache.ddlutils.model.Column; import org.apache.ddlutils.model.Database; +import org.apache.ddlutils.model.ForeignKey; +import org.apache.ddlutils.model.Table; import org.apache.ddlutils.platform.CreationParameters; +import org.apache.ddlutils.platform.DefaultValueHelper; import org.apache.ddlutils.platform.firebird.FirebirdPlatform; import org.apache.ddlutils.platform.interbase.InterbasePlatform; @@ -555,7 +561,112 @@ return getPlatform().readModelFromDatabase(databaseName, catalog, schema, null); } - + + /** + * Returns a copy of the given model adjusted for type changes because of the native type mappings + * which when read back from the database will map to different types. + * + * @param sourceModel The source model + * @return The adjusted model + */ + protected Database adjustModel(Database sourceModel) + { + Database model = new CloneHelper().clone(sourceModel); + + for (int tableIdx = 0; tableIdx < model.getTableCount(); tableIdx++) + { + Table table = model.getTable(tableIdx); + + for (int columnIdx = 0; columnIdx < table.getColumnCount(); columnIdx++) + { + Column column = table.getColumn(columnIdx); + int origType = column.getTypeCode(); + int targetType = getPlatformInfo().getTargetJdbcType(origType); + + // we adjust the column types if the native type would back-map to a + // different jdbc type + if (targetType != origType) + { + column.setTypeCode(targetType); + // we should also adapt the default value + if (column.getDefaultValue() != null) + { + DefaultValueHelper helper = getPlatform().getSqlBuilder().getDefaultValueHelper(); + + column.setDefaultValue(helper.convert(column.getDefaultValue(), origType, targetType)); + } + } + // we also promote the default size if the column has no size + // spec of its own + if ((column.getSize() == null) && getPlatformInfo().hasSize(targetType)) + { + Integer defaultSize = getPlatformInfo().getDefaultSize(targetType); + + if (defaultSize != null) + { + column.setSize(defaultSize.toString()); + } + } + // finally the platform might return a synthetic default value if the column + // is a primary key column + if (getPlatformInfo().isSyntheticDefaultValueForRequiredReturned() && + (column.getDefaultValue() == null) && column.isRequired() && !column.isAutoIncrement()) + { + switch (column.getTypeCode()) + { + case Types.TINYINT: + case Types.SMALLINT: + case Types.INTEGER: + case Types.BIGINT: + column.setDefaultValue("0"); + break; + case Types.REAL: + case Types.FLOAT: + case Types.DOUBLE: + column.setDefaultValue("0.0"); + break; + case Types.BIT: + column.setDefaultValue("false"); + break; + default: + column.setDefaultValue(""); + break; + } + } + if (column.isPrimaryKey() && getPlatformInfo().isPrimaryKeyColumnAutomaticallyRequired()) + { + column.setRequired(true); + } + if (column.isAutoIncrement() && getPlatformInfo().isIdentityColumnAutomaticallyRequired()) + { + column.setRequired(true); + } + } + // we also add the default names to foreign keys that are initially unnamed + for (int fkIdx = 0; fkIdx < table.getForeignKeyCount(); fkIdx++) + { + ForeignKey fk = table.getForeignKey(fkIdx); + + if (fk.getName() == null) + { + fk.setName(getPlatform().getSqlBuilder().getForeignKeyName(table, fk)); + } + } + } + return model; + } + + /** + * Returns the original model adjusted for type changes because of the native type mappings + * which when read back from the database will map to different types. + * + * @return The adjusted model + */ + protected Database getAdjustedModel() + { + return adjustModel(getModel()); + } + /** * Returns the SQL for altering the live database so that it matches the given model. * Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/io/RoundtripTestBase.java URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/io/RoundtripTestBase.java?rev=635228&r1=635227&r2=635228&view=diff ============================================================================== --- db/ddlutils/trunk/src/test/org/apache/ddlutils/io/RoundtripTestBase.java (original) +++ db/ddlutils/trunk/src/test/org/apache/ddlutils/io/RoundtripTestBase.java Sun Mar 9 05:35:44 2008 @@ -36,7 +36,6 @@ import org.apache.ddlutils.dynabean.SqlDynaClass; import org.apache.ddlutils.dynabean.SqlDynaProperty; import org.apache.ddlutils.model.CascadeActionEnum; -import org.apache.ddlutils.model.CloneHelper; import org.apache.ddlutils.model.Column; import org.apache.ddlutils.model.Database; import org.apache.ddlutils.model.ForeignKey; @@ -45,7 +44,6 @@ import org.apache.ddlutils.model.Reference; import org.apache.ddlutils.model.Table; import org.apache.ddlutils.model.TypeMap; -import org.apache.ddlutils.platform.DefaultValueHelper; /** * Base class for database roundtrip (creation & reconstruction from the database). @@ -259,99 +257,6 @@ return getPlatform().fetch(getModel(), getSelectQueryForAllString(table, orderColumn), new Table[] { table }); - } - - /** - * Returns the original model adjusted for type changes because of the native type mappings - * which when read back from the database will map to different types. - * - * @return The adjusted model - */ - protected Database getAdjustedModel() - { - Database model = new CloneHelper().clone(getModel()); - - for (int tableIdx = 0; tableIdx < model.getTableCount(); tableIdx++) - { - Table table = model.getTable(tableIdx); - - for (int columnIdx = 0; columnIdx < table.getColumnCount(); columnIdx++) - { - Column column = table.getColumn(columnIdx); - int origType = column.getTypeCode(); - int targetType = getPlatformInfo().getTargetJdbcType(origType); - - // we adjust the column types if the native type would back-map to a - // different jdbc type - if (targetType != origType) - { - column.setTypeCode(targetType); - // we should also adapt the default value - if (column.getDefaultValue() != null) - { - DefaultValueHelper helper = getPlatform().getSqlBuilder().getDefaultValueHelper(); - - column.setDefaultValue(helper.convert(column.getDefaultValue(), origType, targetType)); - } - } - // we also promote the default size if the column has no size - // spec of its own - if ((column.getSize() == null) && getPlatformInfo().hasSize(targetType)) - { - Integer defaultSize = getPlatformInfo().getDefaultSize(targetType); - - if (defaultSize != null) - { - column.setSize(defaultSize.toString()); - } - } - // finally the platform might return a synthetic default value if the column - // is a primary key column - if (getPlatformInfo().isSyntheticDefaultValueForRequiredReturned() && - (column.getDefaultValue() == null) && column.isRequired() && !column.isAutoIncrement()) - { - switch (column.getTypeCode()) - { - case Types.TINYINT: - case Types.SMALLINT: - case Types.INTEGER: - case Types.BIGINT: - column.setDefaultValue("0"); - break; - case Types.REAL: - case Types.FLOAT: - case Types.DOUBLE: - column.setDefaultValue("0.0"); - break; - case Types.BIT: - column.setDefaultValue("false"); - break; - default: - column.setDefaultValue(""); - break; - } - } - if (column.isPrimaryKey() && getPlatformInfo().isPrimaryKeyColumnAutomaticallyRequired()) - { - column.setRequired(true); - } - if (column.isAutoIncrement() && getPlatformInfo().isIdentityColumnAutomaticallyRequired()) - { - column.setRequired(true); - } - } - // we also add the default names to foreign keys that are initially unnamed - for (int fkIdx = 0; fkIdx < table.getForeignKeyCount(); fkIdx++) - { - ForeignKey fk = table.getForeignKey(fkIdx); - - if (fk.getName() == null) - { - fk.setName(getPlatform().getSqlBuilder().getForeignKeyName(table, fk)); - } - } - } - return model; } /** Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/task/TestDropTablesCommand.java URL: http://svn.apache.org/viewvc/db/ddlutils/trunk/src/test/org/apache/ddlutils/task/TestDropTablesCommand.java?rev=635228&r1=635227&r2=635228&view=diff ============================================================================== --- db/ddlutils/trunk/src/test/org/apache/ddlutils/task/TestDropTablesCommand.java (original) +++ db/ddlutils/trunk/src/test/org/apache/ddlutils/task/TestDropTablesCommand.java Sun Mar 9 05:35:44 2008 @@ -253,5 +253,650 @@ readModelFromDatabase("roundtriptest")); } - // circular fks + /** + * Tests the removal of a table via the names list. + */ + public void testNamesListWithSingleName() + { + final String model1Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='roundtrip1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='roundtrip2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='roundtrip2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='roundtrip1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + final String model2Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='roundtrip2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " </table>\n"+ + "</database>"; + + createDatabase(model1Xml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNames("roundtrip1"); + task.addDropTables(subTask); + task.execute(); + + assertEquals(adjustModel(parseDatabaseFromString(model2Xml)), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests the removal of multiple tables via the names list. + */ + public void testNamesListWithMultipleNames() + { + final String modelXml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='roundtrip1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='roundtrip2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='roundtrip2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='roundtrip1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + + createDatabase(modelXml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNames("roundtrip1,roundtrip2,roundtrip3"); + task.addDropTables(subTask); + task.execute(); + + assertEquals(new Database("roundtriptest"), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests the removal of a table via the names list. + */ + public void testNamesListWithSingleDelimitedName() + { + if (!getPlatformInfo().isDelimitedIdentifiersSupported()) + { + return; + } + + final String model1Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip 1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='Roundtrip 2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='Roundtrip 2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='Roundtrip 1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + final String model2Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip 2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " </table>\n"+ + "</database>"; + + getPlatform().setDelimitedIdentifierModeOn(true); + createDatabase(model1Xml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNames("Roundtrip 1"); + task.addDropTables(subTask); + task.setUseDelimitedSqlIdentifiers(true); + task.execute(); + + assertEquals(adjustModel(parseDatabaseFromString(model2Xml)), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests the removal of multiple tables via the names list. + */ + public void testNamesListWithMultipleDelimitedNames() + { + if (!getPlatformInfo().isDelimitedIdentifiersSupported()) + { + return; + } + + final String modelXml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip 1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='Roundtrip 2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='Roundtrip 2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='Roundtrip 1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + + getPlatform().setDelimitedIdentifierModeOn(true); + createDatabase(modelXml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNames("Roundtrip 2,Roundtrip 1"); + task.addDropTables(subTask); + task.setUseDelimitedSqlIdentifiers(true); + task.execute(); + + assertEquals(new Database("roundtriptest"), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests the removal of a table via the names list. + */ + public void testNamesListWithSingleDelimitedNameWithComma() + { + if (!getPlatformInfo().isDelimitedIdentifiersSupported()) + { + return; + } + + final String model1Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip, 1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='Roundtrip, 2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='Roundtrip, 2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='Roundtrip, 1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + final String model2Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip, 1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " </table>\n"+ + "</database>"; + + getPlatform().setDelimitedIdentifierModeOn(true); + createDatabase(model1Xml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNames("Roundtrip\\, 2"); + task.addDropTables(subTask); + task.setUseDelimitedSqlIdentifiers(true); + task.execute(); + + assertEquals(adjustModel(parseDatabaseFromString(model2Xml)), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests the removal of a table via the names list. + */ + public void testNamesListWithSingleDelimitedNameEndingInComma() + { + if (!getPlatformInfo().isDelimitedIdentifiersSupported()) + { + return; + } + + final String model1Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip 1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='Roundtrip 2,'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='Roundtrip 2,'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='Roundtrip 1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + final String model2Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip 1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " </table>\n"+ + "</database>"; + + getPlatform().setDelimitedIdentifierModeOn(true); + createDatabase(model1Xml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNames("Roundtrip 2\\,"); + task.addDropTables(subTask); + task.setUseDelimitedSqlIdentifiers(true); + task.execute(); + + assertEquals(adjustModel(parseDatabaseFromString(model2Xml)), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests the removal of multiple tables via the names list. + */ + public void testNamesListWithMultipleDelimitedNameWithCommas() + { + if (!getPlatformInfo().isDelimitedIdentifiersSupported()) + { + return; + } + + final String modelXml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip, 1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='Roundtrip 2,'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='Roundtrip 2,'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='Roundtrip, 1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + + getPlatform().setDelimitedIdentifierModeOn(true); + createDatabase(modelXml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNames("Roundtrip\\, 1,Roundtrip 2\\,"); + task.addDropTables(subTask); + task.setUseDelimitedSqlIdentifiers(true); + task.execute(); + + assertEquals(new Database("roundtriptest"), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests an empty names list. + */ + public void testEmptyNamesList() + { + final String modelXml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='roundtrip1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='roundtrip2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='roundtrip2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='roundtrip1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + + createDatabase(modelXml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNames(""); + task.addDropTables(subTask); + task.execute(); + + assertEquals(getAdjustedModel(), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests the removal of a table via a regular expression. + */ + public void testSimpleRegExp() + { + final String model1Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='roundtrip1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='roundtrip2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='roundtrip2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='roundtrip1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + final String model2Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='roundtrip1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " </table>\n"+ + "</database>"; + + createDatabase(model1Xml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNameRegExp(".*2"); + task.addDropTables(subTask); + task.execute(); + + assertEquals(adjustModel(parseDatabaseFromString(model2Xml)), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests the removal of a table via a regular expression. + */ + public void testRegExpInDelimitedIdentifierMode() + { + if (!getPlatformInfo().isDelimitedIdentifiersSupported()) + { + return; + } + + final String model1Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip 1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='Roundtrip 2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='Roundtrip 2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='Roundtrip 1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + final String model2Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip 1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " </table>\n"+ + "</database>"; + + getPlatform().setDelimitedIdentifierModeOn(true); + createDatabase(model1Xml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNameRegExp(".*\\s[2|3]"); + task.addDropTables(subTask); + task.setUseDelimitedSqlIdentifiers(true); + task.execute(); + + assertEquals(adjustModel(parseDatabaseFromString(model2Xml)), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests the removal of multiple tables via a regular expression. + */ + public void testRegExpMultipleTables() + { + final String model1Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='roundtrip1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='roundtrip2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='roundtrip2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='roundtrip1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='roundtrap3'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='roundtrip1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + final String model2Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='roundtrap3'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " </table>\n"+ + "</database>"; + + getPlatform().setDelimitedIdentifierModeOn(true); + createDatabase(model1Xml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNameRegExp(".*trip.*"); + task.addDropTables(subTask); + task.setUseDelimitedSqlIdentifiers(true); + task.execute(); + + assertEquals(adjustModel(parseDatabaseFromString(model2Xml)), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests the removal of multiple tables via a regular expression. + */ + public void testRegExpMultipleTablesInDelimitedIdentifierMode() + { + if (!getPlatformInfo().isDelimitedIdentifiersSupported()) + { + return; + } + + final String model1Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip 1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='Roundtrip 2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='Roundtrip 2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='Roundtrip 1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='Roundtrip A'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='Roundtrip 1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + final String model2Xml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='Roundtrip A'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " </table>\n"+ + "</database>"; + + getPlatform().setDelimitedIdentifierModeOn(true); + createDatabase(model1Xml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNameRegExp(".*\\d"); + task.addDropTables(subTask); + task.setUseDelimitedSqlIdentifiers(true); + task.execute(); + + assertEquals(adjustModel(parseDatabaseFromString(model2Xml)), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests a regular expression that matches nothing. + */ + public void testRegExpMatchingNothing() + { + final String modelXml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='roundtrip1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='roundtrip2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='roundtrip2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='roundtrip1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + + createDatabase(modelXml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNameRegExp(".*\\s\\D"); + task.addDropTables(subTask); + task.execute(); + + assertEquals(getAdjustedModel(), + readModelFromDatabase("roundtriptest")); + } + + /** + * Tests an empty regular expression. + */ + public void testEmptyRegExp() + { + final String modelXml = + "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+ + "<database name='roundtriptest'>\n"+ + " <table name='roundtrip1'>\n"+ + " <column name='pk' type='VARCHAR' size='32' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='INTEGER'/>\n"+ + " <foreign-key foreignTable='roundtrip2'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + " <table name='roundtrip2'>\n"+ + " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+ + " <column name='avalue' type='VARCHAR' size='32'/>\n"+ + " <foreign-key foreignTable='roundtrip1'>\n"+ + " <reference local='avalue' foreign='pk'/>\n"+ + " </foreign-key>\n"+ + " </table>\n"+ + "</database>"; + + createDatabase(modelXml); + + DatabaseToDdlTask task = getDatabaseToDdlTaskInstance(); + DropTablesCommand subTask = new DropTablesCommand(); + + subTask.setTableNameRegExp(""); + task.addDropTables(subTask); + task.execute(); + + assertEquals(getAdjustedModel(), + readModelFromDatabase("roundtriptest")); + } }