You are viewing a plain text version of this content. The canonical link for it is here.
Posted to ddlutils-dev@db.apache.org by to...@apache.org on 2006/05/09 00:20:40 UTC
svn commit: r405198 - in /db/ddlutils/trunk/src:
java/org/apache/ddlutils/alteration/ java/org/apache/ddlutils/model/
java/org/apache/ddlutils/platform/hsqldb/
java/org/apache/ddlutils/platform/postgresql/ test/org/apache/ddlutils/io/
Author: tomdz
Date: Mon May 8 15:20:37 2006
New Revision: 405198
URL: http://svn.apache.org/viewcvs?rev=405198&view=rev
Log:
Enhanced alteration for Derby, PostgreSQL, HsqlDb
Added more alteration tests
Modified:
db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/AddColumnChange.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/ModelComparator.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/hsqldb/HsqlDbBuilder.java
db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlBuilder.java
db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestAlteration.java
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/AddColumnChange.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/AddColumnChange.java?rev=405198&r1=405197&r2=405198&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/AddColumnChange.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/AddColumnChange.java Mon May 8 15:20:37 2006
@@ -30,17 +30,31 @@
{
/** The new column. */
private Column _newColumn;
+ /** The column before which the new column should be added. */
+ private Column _nextColumn;
/**
* Creates a new change object.
*
- * @param table The table to add the column to
- * @param newColumn The new column
+ * @param table The table to add the column to
+ * @param nextColumn The column before which the new column should be added
+ * @param newColumn The new column
*/
- public AddColumnChange(Table table, Column newColumn)
+ public AddColumnChange(Table table, Column nextColumn, Column newColumn)
{
super(table);
- _newColumn = newColumn;
+ _nextColumn = nextColumn;
+ _newColumn = newColumn;
+ }
+
+ /**
+ * Returns the column before which the new column should be added.
+ *
+ * @return The next column
+ */
+ public Column getNextColumn()
+ {
+ return _nextColumn;
}
/**
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/ModelComparator.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/ModelComparator.java?rev=405198&r1=405197&r2=405198&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/ModelComparator.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/alteration/ModelComparator.java Mon May 8 15:20:37 2006
@@ -212,7 +212,9 @@
{
_log.info("Column " + targetColumn.getName() + " needs to be created for table " + sourceTable.getName());
}
- changes.add(new AddColumnChange(sourceTable, targetColumn));
+ changes.add(new AddColumnChange(sourceTable,
+ columnIdx < targetTable.getColumnCount() - 1 ? targetTable.getColumn(columnIdx + 1) :null,
+ targetColumn));
}
else
{
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java?rev=405198&r1=405197&r2=405198&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/model/Table.java Mon May 8 15:20:37 2006
@@ -200,7 +200,7 @@
}
/**
- * Adds the given column at the specified position .
+ * Adds the given column at the specified position.
*
* @param idx The index where to add the column
* @param column The column
@@ -210,6 +210,28 @@
if (column != null)
{
_columns.add(idx, column);
+ }
+ }
+
+ /**
+ * Adds the column after the given previous column.
+ *
+ * @param previousColumn The column to add the new column after; use
+ * <code>null</code> for adding at the begin
+ * @param column The column
+ */
+ public void addColumn(Column previousColumn, Column column)
+ {
+ if (column != null)
+ {
+ if (previousColumn == null)
+ {
+ _columns.add(0, column);
+ }
+ else
+ {
+ _columns.add(_columns.indexOf(previousColumn), column);
+ }
}
}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/hsqldb/HsqlDbBuilder.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/hsqldb/HsqlDbBuilder.java?rev=405198&r1=405197&r2=405198&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/hsqldb/HsqlDbBuilder.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/hsqldb/HsqlDbBuilder.java Mon May 8 15:20:37 2006
@@ -17,8 +17,17 @@
*/
import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
import org.apache.ddlutils.Platform;
+import org.apache.ddlutils.alteration.AddColumnChange;
+import org.apache.ddlutils.alteration.RemoveColumnChange;
+import org.apache.ddlutils.alteration.TableChange;
+import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.Table;
import org.apache.ddlutils.platform.SqlBuilder;
@@ -59,5 +68,103 @@
public String getSelectLastInsertId(Table table)
{
return "CALL IDENTITY()";
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void processTableStructureChanges(Database currentModel,
+ Database desiredModel,
+ Table sourceTable,
+ Table targetTable,
+ Map parameters,
+ List changes) throws IOException
+ {
+ // in order to utilize the ALTER TABLE ADD COLUMN BEFORE statement
+ // we have to apply the add column changes in the correct order
+ // thus we first gather all add column changes and then execute them
+ // Since we get them in target table column order, we can simply
+ // iterate backwards
+ ArrayList addColumnChanges = new ArrayList();
+
+ for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
+ {
+ TableChange change = (TableChange)changeIt.next();
+
+ if (change instanceof AddColumnChange)
+ {
+ addColumnChanges.add(change);
+ changeIt.remove();
+ }
+ }
+ for (ListIterator changeIt = addColumnChanges.listIterator(addColumnChanges.size()); changeIt.hasPrevious();)
+ {
+ AddColumnChange addColumnChange = (AddColumnChange)changeIt.previous();
+
+ processChange(currentModel, desiredModel, addColumnChange);
+ addColumnChange.apply(currentModel);
+ changeIt.remove();
+ }
+
+ for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
+ {
+ TableChange change = (TableChange)changeIt.next();
+
+ if (change instanceof RemoveColumnChange)
+ {
+ RemoveColumnChange removeColumnChange = (RemoveColumnChange)change;
+
+ // HsqlDb can only drop columns that are not part of a primary key
+ if (!removeColumnChange.getColumn().isPrimaryKey())
+ {
+ processChange(currentModel, desiredModel, removeColumnChange);
+ change.apply(currentModel);
+ changeIt.remove();
+ }
+ }
+ }
+ }
+
+ /**
+ * Processes the addition of a column to a table.
+ *
+ * @param currentModel The current database schema
+ * @param desiredModel The desired database schema
+ * @param change The change object
+ */
+ protected void processChange(Database currentModel,
+ Database desiredModel,
+ AddColumnChange change) throws IOException
+ {
+ print("ALTER TABLE ");
+ printlnIdentifier(getTableName(change.getChangedTable()));
+ printIndent();
+ print("ADD COLUMN ");
+ writeColumn(change.getChangedTable(), change.getNewColumn());
+ if (change.getNextColumn() != null)
+ {
+ print(" BEFORE ");
+ printIdentifier(getColumnName(change.getNextColumn()));
+ }
+ printEndOfStatement();
+ }
+
+ /**
+ * Processes the removal of a column from a table.
+ *
+ * @param currentModel The current database schema
+ * @param desiredModel The desired database schema
+ * @param change The change object
+ */
+ protected void processChange(Database currentModel,
+ Database desiredModel,
+ RemoveColumnChange change) throws IOException
+ {
+ print("ALTER TABLE ");
+ printlnIdentifier(getTableName(change.getChangedTable()));
+ printIndent();
+ print("DROP COLUMN ");
+ printIdentifier(getColumnName(change.getColumn()));
+ printEndOfStatement();
}
}
Modified: db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlBuilder.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlBuilder.java?rev=405198&r1=405197&r2=405198&view=diff
==============================================================================
--- db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlBuilder.java (original)
+++ db/ddlutils/trunk/src/java/org/apache/ddlutils/platform/postgresql/PostgreSqlBuilder.java Mon May 8 15:20:37 2006
@@ -17,9 +17,14 @@
*/
import java.io.IOException;
+import java.util.Iterator;
+import java.util.List;
import java.util.Map;
import org.apache.ddlutils.Platform;
+import org.apache.ddlutils.alteration.AddColumnChange;
+import org.apache.ddlutils.alteration.RemoveColumnChange;
+import org.apache.ddlutils.alteration.TableChange;
import org.apache.ddlutils.model.Column;
import org.apache.ddlutils.model.Database;
import org.apache.ddlutils.model.Index;
@@ -153,5 +158,87 @@
}
return result.toString();
}
+ }
+
+ /**
+ * {@inheritDoc}
+ */
+ protected void processTableStructureChanges(Database currentModel,
+ Database desiredModel,
+ Table sourceTable,
+ Table targetTable,
+ Map parameters,
+ List changes) throws IOException
+ {
+ for (Iterator changeIt = changes.iterator(); changeIt.hasNext();)
+ {
+ TableChange change = (TableChange)changeIt.next();
+
+ if (change instanceof AddColumnChange)
+ {
+ AddColumnChange addColumnChange = (AddColumnChange)change;
+
+ // We can only use PostgreSQL-specific SQL if
+ // * the column is not set to NOT NULL (the constraint would be applied immediately
+ // which will not work if there is already data in the table)
+ // * the column has no default value (it would be applied after the change which
+ // means that PostgreSQL would behave differently from other databases where the
+ // default is applied to every column)
+ // * the column is added at the end of the table (PostgreSQL does not support
+ // insertion of a column)
+ if (!addColumnChange.getNewColumn().isRequired() &&
+ (addColumnChange.getNewColumn().getDefaultValue() == null) &&
+ (addColumnChange.getNextColumn() == null))
+ {
+ processChange(currentModel, desiredModel, addColumnChange);
+ change.apply(currentModel);
+ changeIt.remove();
+ }
+ }
+ else if (change instanceof RemoveColumnChange)
+ {
+ processChange(currentModel, desiredModel, (RemoveColumnChange)change);
+ change.apply(currentModel);
+ changeIt.remove();
+ }
+ }
+ }
+
+ /**
+ * Processes the addition of a column to a table.
+ *
+ * @param currentModel The current database schema
+ * @param desiredModel The desired database schema
+ * @param change The change object
+ */
+ protected void processChange(Database currentModel,
+ Database desiredModel,
+ AddColumnChange change) throws IOException
+ {
+ print("ALTER TABLE ");
+ printlnIdentifier(getTableName(change.getChangedTable()));
+ printIndent();
+ print("ADD COLUMN ");
+ writeColumn(change.getChangedTable(), change.getNewColumn());
+ printEndOfStatement();
+ }
+
+ /**
+ * Processes the removal of a column from a table.
+ *
+ * @param currentModel The current database schema
+ * @param desiredModel The desired database schema
+ * @param change The change object
+ */
+ protected void processChange(Database currentModel,
+ Database desiredModel,
+ RemoveColumnChange change) throws IOException
+ {
+ print("ALTER TABLE ");
+ printlnIdentifier(getTableName(change.getChangedTable()));
+ printIndent();
+ print("DROP COLUMN ");
+ printIdentifier(getColumnName(change.getColumn()));
+ printEndOfStatement();
}
}
Modified: db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestAlteration.java
URL: http://svn.apache.org/viewcvs/db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestAlteration.java?rev=405198&r1=405197&r2=405198&view=diff
==============================================================================
--- db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestAlteration.java (original)
+++ db/ddlutils/trunk/src/test/org/apache/ddlutils/io/TestAlteration.java Mon May 8 15:20:37 2006
@@ -219,7 +219,7 @@
}
/**
- * Tests the addition of a column default value.
+ * Tests the addition of a column's default value.
*/
public void testAddDefault()
{
@@ -291,7 +291,7 @@
}
/**
- * Tests the dropping of a column default value.
+ * Tests the removal of a column default value.
*/
public void testDropDefault()
{
@@ -327,10 +327,15 @@
}
/**
- * Tests the making a column auto-increment.
+ * Tests the change of a column's auto-increment state.
*/
public void testMakeAutoIncrement()
{
+ if (!getPlatformInfo().isNonPKIdentityColumnsSupported())
+ {
+ return;
+ }
+
final String model1Xml =
"<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
"<database name='roundtriptest'>\n"+
@@ -366,10 +371,15 @@
}
/**
- * Tests the dropping the column auto-increment status.
+ * Tests the removal the column auto-increment status.
*/
public void testDropAutoIncrement()
{
+ if (!getPlatformInfo().isNonPKIdentityColumnsSupported())
+ {
+ return;
+ }
+
final String model1Xml =
"<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
"<database name='roundtriptest'>\n"+
@@ -402,7 +412,7 @@
}
/**
- * Tests the adding a column.
+ * Tests the addition of a column.
*/
public void testAddColumn()
{
@@ -418,7 +428,7 @@
"<database name='roundtriptest'>\n"+
" <table name='roundtrip'>\n"+
" <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
- " <column name='avalue' type='INTEGER' default='2' required='true'/>\n"+
+ " <column name='avalue' type='VARCHAR' size='32'/>\n"+
" </table>\n"+
"</database>";
@@ -433,11 +443,122 @@
List beans = getRows("roundtrip");
+ assertEquals((Object)null, beans.get(0), "avalue");
+ }
+
+ /**
+ * Tests the addition of several columns.
+ */
+ public void testAddColumns()
+ {
+ final String model1Xml =
+ "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+ "<database name='roundtriptest'>\n"+
+ " <table name='roundtrip'>\n"+
+ " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+ " <column name='avalue3' type='DOUBLE' default='1.0'/>\n"+
+ " </table>\n"+
+ "</database>";
+ final String model2Xml =
+ "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+ "<database name='roundtriptest'>\n"+
+ " <table name='roundtrip'>\n"+
+ " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+ " <column name='avalue1' type='VARCHAR' size='32'/>\n"+
+ " <column name='avalue2' type='INTEGER' required='true' default='0'/>\n"+
+ " <column name='avalue3' type='DOUBLE' default='1.0'/>\n"+
+ " <column name='avalue4' type='CHAR' size='16'/>\n"+
+ " </table>\n"+
+ "</database>";
+
+ createDatabase(model1Xml);
+
+ insertRow("roundtrip", new Object[] { new Integer(1), new Double(3.0) });
+
+ alterDatabase(model2Xml);
+
+ assertEquals(getAdjustedModel(),
+ readModelFromDatabase("roundtriptest"));
+
+ List beans = getRows("roundtrip");
+
+ assertEquals((Object)null, beans.get(0), "avalue1");
+ assertEquals(new Integer(0), beans.get(0), "avalue2");
+ assertEquals((Object)null, beans.get(0), "avalue4");
+ }
+
+ /**
+ * Tests the addition of a column with a default value.
+ */
+ public void testAddColumnWithDefault()
+ {
+ final String model1Xml =
+ "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+ "<database name='roundtriptest'>\n"+
+ " <table name='roundtrip'>\n"+
+ " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+ " </table>\n"+
+ "</database>";
+ final String model2Xml =
+ "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+ "<database name='roundtriptest'>\n"+
+ " <table name='roundtrip'>\n"+
+ " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+ " <column name='avalue' type='INTEGER' default='2'/>\n"+
+ " </table>\n"+
+ "</database>";
+
+ createDatabase(model1Xml);
+
+ insertRow("roundtrip", new Object[] { new Integer(1) });
+
+ alterDatabase(model2Xml);
+
+ assertEquals(getAdjustedModel(),
+ readModelFromDatabase("roundtriptest"));
+
+ List beans = getRows("roundtrip");
+
+ assertEquals(new Integer(2), beans.get(0), "avalue");
+ }
+
+ /**
+ * Tests the addition of a column that is set to NOT NULL.
+ */
+ public void testAddRequiredColumn()
+ {
+ final String model1Xml =
+ "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+ "<database name='roundtriptest'>\n"+
+ " <table name='roundtrip'>\n"+
+ " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+ " </table>\n"+
+ "</database>";
+ final String model2Xml =
+ "<?xml version='1.0' encoding='ISO-8859-1'?>\n"+
+ "<database name='roundtriptest'>\n"+
+ " <table name='roundtrip'>\n"+
+ " <column name='pk' type='INTEGER' primaryKey='true' required='true'/>\n"+
+ " <column name='avalue' type='INTEGER' default='2' required='true'/>\n"+
+ " </table>\n"+
+ "</database>";
+
+ createDatabase(model1Xml);
+
+ insertRow("roundtrip", new Object[] { new Integer(1) });
+
+ alterDatabase(model2Xml);
+
+ assertEquals(getAdjustedModel(),
+ readModelFromDatabase("roundtriptest"));
+
+ List beans = getRows("roundtrip");
+
assertEquals(new Integer(2), beans.get(0), "avalue");
}
/**
- * Tests the dropping a column.
+ * Tests the removal of a column.
*/
public void testDropColumn()
{
@@ -472,7 +593,7 @@
}
/**
- * Tests the adding a column to the pk.
+ * Tests the addition of a column to the pk.
*/
public void testAddColumnToPK()
{
@@ -508,7 +629,7 @@
}
/**
- * Tests the removing a column from the pk.
+ * Tests the removal of a column from the pk.
*/
public void testRemoveColumnFromPK()
{
@@ -544,7 +665,7 @@
}
/**
- * Tests the adding a pk column.
+ * Tests the addition of a pk column.
*/
public void testAddPKColumn()
{
@@ -579,7 +700,7 @@
}
/**
- * Tests the adding a primary key and a column.
+ * Tests the addition of a primary key and a column.
*/
public void testAddPKAndColumn()
{
@@ -614,7 +735,7 @@
}
/**
- * Tests the adding a primary key and a primary key column.
+ * Tests the addition of a primary key and a primary key column.
*/
public void testAddPKAndPKColumn()
{
@@ -649,7 +770,7 @@
}
/**
- * Tests the dropping of a pk column.
+ * Tests the removal of a pk column.
*/
public void testDropPKColumn()
{
@@ -684,7 +805,7 @@
}
/**
- * Tests the adding of an index.
+ * Tests the addition of an index.
*/
public void testAddIndex()
{
@@ -727,7 +848,7 @@
}
/**
- * Tests the adding of an unique index.
+ * Tests the addition of an unique index.
*/
public void testAddUniqueIndex()
{
@@ -766,7 +887,7 @@
}
/**
- * Tests the dropping of an unique index.
+ * Tests the removal of an unique index.
*/
public void testDropUniqueIndex()
{
@@ -809,7 +930,7 @@
}
/**
- * Tests the adding of a column to an index.
+ * Tests the addition of a column to an index.
*/
public void testAddColumnToIndex()
{
@@ -855,7 +976,7 @@
}
/**
- * Tests the removing of a column from an index.
+ * Tests the removal of a column from an index.
*/
public void testRemoveColumnFromUniqueIndex()
{
@@ -901,7 +1022,7 @@
}
/**
- * Tests the adding a foreign key.
+ * Tests the addition of a foreign key.
*/
public void testAddFK()
{
@@ -950,7 +1071,7 @@
}
/**
- * Tests the dropping of a foreign key.
+ * Tests the removal of a foreign key.
*/
public void testDropFK()
{
@@ -1006,7 +1127,7 @@
}
/**
- * Tests the adding a reference to a foreign key.
+ * Tests the addition of a reference to a foreign key.
*/
public void testAddReferenceToFK()
{
@@ -1063,7 +1184,7 @@
}
/**
- * Tests the removing a reference from a foreign key.
+ * Tests the removal of a reference from a foreign key.
*/
public void testRemoveReferenceFromFK()
{
@@ -1118,7 +1239,7 @@
}
/**
- * Tests the adding a table.
+ * Tests the addition of a table.
*/
public void testAddTable1()
{
@@ -1159,7 +1280,7 @@
}
/**
- * Tests the adding a table.
+ * Tests the addition of a table.
*/
public void testAddTable2()
{
@@ -1224,7 +1345,7 @@
}
/**
- * Tests the removing a table.
+ * Tests the removal of a table.
*/
public void testRemoveTable1()
{
@@ -1263,7 +1384,7 @@
}
/**
- * Tests the removing a table.
+ * Tests the removal of a table.
*/
public void testRemoveTable2()
{