db-derby-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From kahat...@apache.org
Subject svn commit: r1555703 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/types/ engine/org/apache/derby/impl/sql/catalog/ testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/
Date Mon, 06 Jan 2014 10:06:11 GMT
Author: kahatlen
Date: Mon Jan  6 10:06:10 2014
New Revision: 1555703

URL: http://svn.apache.org/r1555703
Log:
DERBY-5866: Triggers fire out of order

In order to avoid ambiguities around switch from daylight saving time
to standard time, and other time zone changes, store the trigger
creation timestamps in Coordinated Universal Time (UTC) instead of the
local time zone.

Only use UTC if the database has been upgraded to 10.11 format, so
that the change won't cause problems on downgrade.

Modified:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLTimestamp.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SYSTRIGGERSRowFactory.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/Changes10_11.java

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLTimestamp.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLTimestamp.java?rev=1555703&r1=1555702&r2=1555703&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLTimestamp.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLTimestamp.java Mon Jan
 6 10:06:10 2014
@@ -382,10 +382,28 @@ public final class SQLTimestamp extends 
 	/** no-arg constructor required by Formattable */
 	public SQLTimestamp() { }
 
+    /**
+     * Create a new SQLTimestamp instance that represents the specified
+     * Timestamp in the time zone of the given Calendar.
+     * @param value the Timestamp value to be represented by this instance
+     * @param cal the time zone of the calendar is used to construct the
+     * database timestamp value
+     * @throws StandardException if an error occurs
+     */
+    public SQLTimestamp(Timestamp value, Calendar cal) throws StandardException
+    {
+        setValue(value, cal);
+    }
 
+    /**
+     * Create a new SQLTimestamp instance that represents the specified
+     * Timestamp in the local time zone.
+     * @param value the Timestamp value to be represented by this instance
+     * @throws StandardException if an error occurs
+     */
 	public SQLTimestamp(Timestamp value) throws StandardException
 	{
-		setValue(value, (Calendar) null);
+        this(value, (Calendar) null);
 	}
 
 	SQLTimestamp(int encodedDate, int encodedTime, int nanos) {

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SYSTRIGGERSRowFactory.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SYSTRIGGERSRowFactory.java?rev=1555703&r1=1555702&r2=1555703&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SYSTRIGGERSRowFactory.java
(original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/sql/catalog/SYSTRIGGERSRowFactory.java
Mon Jan  6 10:06:10 2014
@@ -50,6 +50,8 @@ import org.apache.derby.shared.common.sa
 import org.apache.derby.iapi.types.SQLTimestamp;
 import java.sql.Timestamp;
 import java.sql.Types;
+import java.util.Calendar;
+import java.util.TimeZone;
 
 /**
  * Factory for creating a SYSTRIGGERS row.
@@ -110,6 +112,9 @@ public class SYSTRIGGERSRowFactory exten
 		,"c013800d-00d7-c025-480d-000a0a411200"	// SYSTRIGGERS_INDEX3
 	};
 
+    /** TimeZone object representing Coordinated Universal Time. */
+    private final static TimeZone UTC = TimeZone.getTimeZone("UTC");
+
     private final DataDictionary dataDictionary;
 
 	/////////////////////////////////////////////////////////////////////////////
@@ -230,7 +235,10 @@ public class SYSTRIGGERSRowFactory exten
 		row.setColumn(3, new SQLChar((suuid == null) ? null : suuid.toString()));
 
 		/* 4th column is CREATIONTIMESTAMP */
-		row.setColumn(4, new SQLTimestamp(createTime));
+        SQLTimestamp creationTimestamp = (createTime == null)
+            ? new SQLTimestamp(null)
+            : new SQLTimestamp(createTime, getCalendarForCreationTimestamp());
+        row.setColumn(4, creationTimestamp);
 
 		/* 5th column is EVENT */
 		row.setColumn(5, new SQLChar(event));
@@ -283,6 +291,27 @@ public class SYSTRIGGERSRowFactory exten
 		return row;
 	}
 
+    /**
+     * Get a calendar instance with the correct time zone for storing and
+     * retrieving creation timestamps. Creation timestamps are stored in UTC
+     * to avoid ambiguities around the change from daylight saving time to
+     * standard time, or other time zone changes. If the data dictionary
+     * version is less than 10.11, however, the timestamps are stored in the
+     * local time zone.
+     *
+     * @return a calendar instance that can be used for storing and retrieving
+     *   trigger creation timestamps
+     * @throws StandardException if an error occurs
+     */
+    private Calendar getCalendarForCreationTimestamp()
+            throws StandardException {
+        if (dataDictionary.checkVersion(
+                DataDictionary.DD_VERSION_DERBY_10_11, null)) {
+            return Calendar.getInstance(UTC);
+        } else {
+            return Calendar.getInstance();
+        }
+    }
 
 	///////////////////////////////////////////////////////////////////////////
 	//
@@ -361,7 +390,7 @@ public class SYSTRIGGERSRowFactory exten
 
 		// 4th column is CREATIONTIMESTAMP (TIMESTAMP)
 		col = row.getColumn(4);
-		createTime = (Timestamp) col.getObject();
+        createTime = col.getTimestamp(getCalendarForCreationTimestamp());
 
 		// 5th column is EVENT (char(1))
 		col = row.getColumn(5);

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/Changes10_11.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/Changes10_11.java?rev=1555703&r1=1555702&r2=1555703&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/Changes10_11.java
(original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/upgradeTests/Changes10_11.java
Mon Jan  6 10:06:10 2014
@@ -227,4 +227,49 @@ public class Changes10_11 extends Upgrad
             }
         }
     }
+
+    /**
+     * Create a trigger in each upgrade phase and verify that they fire in
+     * the order in which they were created. DERBY-5866 changed how the
+     * trigger creation timestamp was stored (from local time zone to UTC),
+     * and we want to test that this change doesn't affect the trigger
+     * execution order when the triggers have been created with different
+     * versions.
+     */
+    public void testDerby5866TriggerExecutionOrder() throws SQLException {
+        Statement s = createStatement();
+        switch (getPhase()) {
+            case PH_CREATE:
+                s.execute("create table d5866_t1(x int)");
+                s.execute("create table d5866_t2(x int "
+                        + "generated always as identity, y varchar(100))");
+                s.execute("create trigger d5866_create after insert "
+                        + "on d5866_t1 for each statement mode db2sql "
+                        + "insert into d5866_t2(y) values 'CREATE'");
+                break;
+            case PH_SOFT_UPGRADE:
+                s.execute("create trigger d5866_soft after insert on d5866_t1 "
+                        + "insert into d5866_t2(y) values 'SOFT UPGRADE'");
+                break;
+            case PH_POST_SOFT_UPGRADE:
+                s.execute("create trigger d5866_post_soft after insert "
+                        + "on d5866_t1 for each statement mode db2sql "
+                        + "insert into d5866_t2(y) values 'POST SOFT UPGRADE'");
+                break;
+            case PH_HARD_UPGRADE:
+                s.execute("create trigger d5866_hard after insert on d5866_t1 "
+                        + "insert into d5866_t2(y) values 'HARD UPGRADE'");
+
+                // Fire all the triggers and verify that they executed in
+                // the right order.
+                s.execute("insert into d5866_t1 values 1,2,3");
+                JDBC.assertFullResultSet(
+                        s.executeQuery("select y from d5866_t2 order by x"),
+                        new String[][] {
+                            { "CREATE" }, { "SOFT UPGRADE" },
+                            { "POST SOFT UPGRADE" }, { "HARD UPGRADE" }
+                        });
+                break;
+        }
+    }
 }



Mime
View raw message