You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2011/06/06 10:31:52 UTC
svn commit: r1132546 - in /db/derby/code/trunk/java:
engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/BasicSetup.java
Author: kahatlen
Date: Mon Jun 6 08:31:51 2011
New Revision: 1132546
URL: http://svn.apache.org/viewvc?rev=1132546&view=rev
Log:
DERBY-3870: Concurrent Inserts of rows with XML data results in an exception
Allow databases that contain triggers with XML operators to be
upgraded from a version without the fix for this issue to a fixed
version. It used to fail because it couldn't deserialize the old plan
for the trigger. Fix it by not trying to deserialize the plan before
invalidating it.
Modified:
db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/BasicSetup.java
Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java?rev=1132546&r1=1132545&r2=1132546&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/DataDictionaryImpl.java Mon Jun 6 08:31:51 2011
@@ -4580,6 +4580,9 @@ public final class DataDictionaryImpl
/**
* Get every statement in this database.
* Return the SPSDescriptors in an list.
+ * The returned descriptors don't contain the compiled statement, so it
+ * it safe to call this method during upgrade when it isn't known if the
+ * saved statement can still be deserialized with the new version.
*
* @return the list of descriptors
*
@@ -4592,7 +4595,23 @@ public final class DataDictionaryImpl
List list = newSList();
+ // DERBY-3870: The compiled plan may not be possible to deserialize
+ // during upgrade. Skip the column that contains the compiled plan to
+ // prevent deserialization errors when reading the rows. We don't care
+ // about the value in that column, since this method is only called
+ // when we want to drop or invalidate rows in SYSSTATEMENTS.
+ FormatableBitSet cols = new FormatableBitSet(
+ ti.getCatalogRowFactory().getHeapColumnCount());
+ for (int i = 0; i < cols.size(); i++) {
+ if (i + 1 == SYSSTATEMENTSRowFactory.SYSSTATEMENTS_CONSTANTSTATE) {
+ cols.clear(i);
+ } else {
+ cols.set(i);
+ }
+ }
+
getDescriptorViaHeap(
+ cols,
(ScanQualifier[][]) null,
ti,
(TupleDescriptor) null,
@@ -4647,6 +4666,7 @@ public final class DataDictionaryImpl
GenericDescriptorList list = new GenericDescriptorList();
getDescriptorViaHeap(
+ null,
(ScanQualifier[][]) null,
ti,
(TupleDescriptor) null,
@@ -7039,10 +7059,7 @@ public final class DataDictionaryImpl
false);
ConglomerateDescriptorList cdl = new ConglomerateDescriptorList();
- getDescriptorViaHeap(scanQualifier,
- ti,
- null,
- cdl);
+ getDescriptorViaHeap(null, scanQualifier, ti, null, cdl);
int size = cdl.size();
ConglomerateDescriptor[] cda = new ConglomerateDescriptor[size];
@@ -9475,6 +9492,8 @@ public final class DataDictionaryImpl
* Return a (single or list of) catalog row descriptor(s) from a
* system table where the access a heap scan
*
+ * @param columns which columns to fetch from the system
+ * table, or null to fetch all columns
* @param scanQualifiers qualifiers
* @param ti The TabInfoImpl to use
* @param parentTupleDescriptor The parentDescriptor, if applicable.
@@ -9486,6 +9505,7 @@ public final class DataDictionaryImpl
* @exception StandardException Thrown on error
*/
protected TupleDescriptor getDescriptorViaHeap(
+ FormatableBitSet columns,
ScanQualifier [][] scanQualifiers,
TabInfoImpl ti,
TupleDescriptor parentTupleDescriptor,
@@ -9513,7 +9533,7 @@ public final class DataDictionaryImpl
0, // for read
TransactionController.MODE_TABLE,
TransactionController.ISOLATION_REPEATABLE_READ,
- (FormatableBitSet) null, // all fields as objects
+ columns,
(DataValueDescriptor[]) null, // start position - first row
0, // startSearchOperation - none
scanQualifiers, // scanQualifier,
Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/BasicSetup.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/BasicSetup.java?rev=1132546&r1=1132545&r2=1132546&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/BasicSetup.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/BasicSetup.java Mon Jun 6 08:31:51 2011
@@ -29,6 +29,7 @@ import java.util.ArrayList;
import org.apache.derbyTesting.junit.JDBC;
import org.apache.derbyTesting.junit.TestConfiguration;
+import org.apache.derbyTesting.junit.XML;
import junit.framework.Test;
import junit.framework.TestSuite;
@@ -43,7 +44,13 @@ public class BasicSetup extends UpgradeC
TestSuite suite = new TestSuite("Upgrade basic setup");
suite.addTestSuite(BasicSetup.class);
-
+
+ if (XML.classpathMeetsXMLReqs()) {
+ // Only test XML operators if they are supported by the version
+ // we upgrade to.
+ suite.addTest(new BasicSetup("xmlTestTriggerWithXMLOperators"));
+ }
+
return suite;
}
@@ -772,4 +779,62 @@ public class BasicSetup extends UpgradeC
return buffer.toString();
}
//End of helper methods for testExhuastivePermutationOfTriggerColumns
+
+ /**
+ * Test that triggers that use XML operators work after upgrade. The
+ * first fix for DERBY-3870 broke upgrade of such triggers because the
+ * old execution plans failed to deserialize on the new version.
+ */
+ public void xmlTestTriggerWithXMLOperators() throws SQLException {
+ if (!oldAtLeast(10, 3)) {
+ // Before 10.3, the CREATE TRIGGER statement used in the test
+ // failed with a syntax error. Skip the test for older versions.
+ return;
+ }
+
+ Statement s = createStatement();
+
+ if (getPhase() == PH_CREATE) {
+ // Create test tables and a trigger that uses XML operators with
+ // the old version.
+ s.execute("create table d3870_t1(i int, x varchar(100))");
+ s.execute("create table d3870_t2(i int)");
+ try {
+ s.execute("create trigger d3870_tr after insert on d3870_t1 " +
+ "for each statement insert into d3870_t2 " +
+ "select i from d3870_t1 where " +
+ "xmlexists('//a' passing by ref " +
+ "xmlparse(document x preserve whitespace))");
+ } catch (SQLException sqle) {
+ // The CREATE TRIGGER statement will fail if the XML classpath
+ // requirements aren't satisfied for the old version. That's
+ // OK, but we'll have to skip the test for this combination.
+ assertSQLState("XML00", sqle);
+ return;
+ }
+ } else {
+ // Delete the rows to start the test from a known state in each
+ // of the phases.
+ s.executeUpdate("delete from d3870_t1");
+ s.executeUpdate("delete from d3870_t2");
+ }
+
+ // Check if the trigger exists. It won't exist if the XML requirements
+ // weren't satisfied for the old version. If we don't have the trigger,
+ // we skip the rest of the test.
+ ResultSet rs = s.executeQuery(
+ "select 1 from sys.systriggers where triggername = 'D3870_TR'");
+ boolean hasTrigger = rs.next();
+ rs.close();
+
+ // Verify that the trigger works both before and after upgrade.
+ if (hasTrigger) {
+ s.execute("insert into d3870_t1 values " +
+ "(1, '<a/>'), (2, '<b/>'), (3, '<c/>')");
+
+ JDBC.assertSingleValueResultSet(
+ s.executeQuery("select * from d3870_t2"), "1");
+ }
+ }
+
}