Author: rhillegas
Date: Thu Apr 26 14:38:44 2012
New Revision: 1330877
URL: http://svn.apache.org/viewvc?rev=1330877&view=rev
Log:
DERBY-5679: Fill nonexistent columns with NULLS during update of later column in the row.
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/StoredPage.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/AlterTableTest.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/StoredPage.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/StoredPage.java?rev=1330877&r1=1330876&r2=1330877&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/StoredPage.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/raw/data/StoredPage.java Thu
Apr 26 14:38:44 2012
@@ -327,10 +327,15 @@ public class StoredPage extends CachedPa
* COLUMN_LONG - this is a known long column, therefore we will
* store part of the column on the current page and
* overflow the rest if necessary.
+ * COLUMN_CREATE_NULL - the column was recently added.
+ * it doesn't actually exist in the on-disk row yet.
+ * we will need to put a null in it as soon as possible.
+ * see DERBY-5679.
**/
protected static final int COLUMN_NONE = 0;
protected static final int COLUMN_FIRST = 1;
protected static final int COLUMN_LONG = 2;
+ protected static final int COLUMN_CREATE_NULL = 3;
/**
@@ -3968,12 +3973,14 @@ public class StoredPage extends CachedPa
else
{
// this is an update that is increasing the number of
- // columns but not providing any value, strange ...
-
+ // columns but not providing any value. this can happen
+ // if you are updating a new column after using
+ // ALTER TABLE to add a couple new columns.
+ // see DERBY-5679.
spaceAvailable =
logColumn(
null, 0, out, spaceAvailable,
- columnFlag, overflowThreshold);
+ COLUMN_CREATE_NULL, overflowThreshold);
}
}
@@ -6177,7 +6184,7 @@ public class StoredPage extends CachedPa
}
}
- if (column == null)
+ if ( (column == null) && (columnFlag != COLUMN_CREATE_NULL))
{
fieldStatus = StoredFieldHeader.setNonexistent(fieldStatus);
headerLength =
@@ -6300,11 +6307,28 @@ public class StoredPage extends CachedPa
}
}
+ else if ( columnFlag == COLUMN_CREATE_NULL )
+ {
+ //
+ // This block handles the case when a couple columns have been added
+ // recently and now one of the later columns is being updated. Newly added columns
+ // which appear in the row before the updated column don't actually have
+ // any values yet. We stuff NULLs into those newly added columns here.
+ // This fixes DERBY-5679.
+ //
+ fieldStatus = StoredFieldHeader.setNull(fieldStatus, true);
+
+ // header is written with 0 length here.
+ headerLength =
+ StoredFieldHeader.write(
+ logicalDataOut, fieldStatus,
+ fieldDataLength, slotFieldSize);
+ }
else if (column instanceof DataValueDescriptor)
{
DataValueDescriptor sColumn = (DataValueDescriptor) column;
- boolean isNull = sColumn.isNull();
+ boolean isNull = (columnFlag == COLUMN_CREATE_NULL) || sColumn.isNull();
if (isNull)
{
fieldStatus = StoredFieldHeader.setNull(fieldStatus, true);
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/AlterTableTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/AlterTableTest.java?rev=1330877&r1=1330876&r2=1330877&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/AlterTableTest.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/AlterTableTest.java
Thu Apr 26 14:38:44 2012
@@ -3667,4 +3667,42 @@ public final class AlterTableTest extend
s.execute("alter table \"\"\"\".\"\"\"\" " +
"alter column \"\"\"\" set increment by 2");
}
+
+ /**
+ * Verify that rollback works properly if a column with a null default
+ * is added and then the table is updated. See DERBY-5679.
+ */
+ public void test_5679() throws Exception
+ {
+ Statement s = createStatement();
+ ResultSet rs;
+
+ String[][] rowBefore = new String[][]{ { "before", null, "before" } };
+ String[][] rowAfter = new String[][]{ { "after", "after", "after" } };
+
+ // create a table, insert a row, add two columns, then update one of the columns
+ s.execute( "create table t_5679(name1 varchar(10))" );
+ s.execute( "insert into t_5679(name1) values('before')" );
+ s.execute( "alter table t_5679 add column str1 varchar(10)" );
+ s.execute( "alter table t_5679 add column str2 varchar(10)" );
+ s.execute( "update t_5679 set str2 = 'before'" );
+
+ rs = s.executeQuery( "select * from t_5679" );
+ JDBC.assertFullResultSet( rs, rowBefore );
+
+ // now update the row and rollback
+ setAutoCommit( false );
+ s.execute( "update t_5679 set name1='after', str1='after', str2='after'" );
+ rs = s.executeQuery( "select * from t_5679" );
+ JDBC.assertFullResultSet( rs, rowAfter );
+ rollback();
+ setAutoCommit( true );
+
+ // all columns of the row should have reverted
+ rs = s.executeQuery( "select * from t_5679" );
+ JDBC.assertFullResultSet( rs, rowBefore );
+
+ s.execute( "drop table t_5679" );
+ }
+
}
|