From derby-commits-return-11970-apmail-db-derby-commits-archive=db.apache.org@db.apache.org Fri Aug 14 19:13:03 2009 Return-Path: Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: (qmail 11089 invoked from network); 14 Aug 2009 19:13:03 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.3) by minotaur.apache.org with SMTP; 14 Aug 2009 19:13:03 -0000 Received: (qmail 16460 invoked by uid 500); 14 Aug 2009 19:13:10 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 16405 invoked by uid 500); 14 Aug 2009 19:13:10 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 16396 invoked by uid 99); 14 Aug 2009 19:13:10 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 14 Aug 2009 19:13:10 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 14 Aug 2009 19:13:08 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id A3E6323888EC; Fri, 14 Aug 2009 19:12:47 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r804327 - in /db/derby/code/branches/10.4/java: engine/org/apache/derby/impl/sql/execute/ testing/org/apache/derbyTesting/functionTests/tests/lang/ Date: Fri, 14 Aug 2009 19:12:47 -0000 To: derby-commits@db.apache.org From: dag@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090814191247.A3E6323888EC@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: dag Date: Fri Aug 14 19:12:46 2009 New Revision: 804327 URL: http://svn.apache.org/viewvc?rev=804327&view=rev Log: DERBY-4330 NullPointerException or assert failure when re-executing PreparedStatement after lock timeout Backported fix from trunk as: svn merge -c 804271 https://svn.apache.org/repos/asf/db/derby/code/trunk Patch derby-4330c fixes this issue. The problem is that when a timeout happens (or a deadlock), the result set tree for prepared statements for some queries is partically in a closed, partially in an open state. (The issue was reported for a join query, but exists for others queries as well). This causes problems when the result set tree is being reused, i.e. when the prpared statement is attempted re-executed after the timeout, since the tree is expected to be fully closed at that time, cuasing the assert or NPE. The fix ensures that the tree is left in a fully closed state in such cases. Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/DistinctScalarAggregateResultSet.java db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/GroupedAggregateResultSet.java db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/JoinResultSet.java db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/SetOpResultSet.java db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/SortResultSet.java db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/UnionResultSet.java db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ResultSetsFromPreparedStatementTest.java Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/DistinctScalarAggregateResultSet.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/DistinctScalarAggregateResultSet.java?rev=804327&r1=804326&r2=804327&view=diff ============================================================================== --- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/DistinctScalarAggregateResultSet.java (original) +++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/DistinctScalarAggregateResultSet.java Fri Aug 14 19:12:46 2009 @@ -138,10 +138,20 @@ source.openCore(); - /* - ** Load up the sorter because we have something to sort. - */ - scanController = loadSorter(); + try { + /* + ** Load up the sorter because we have something to sort. + */ + scanController = loadSorter(); + } catch (StandardException e) { + // DERBY-4330 Result set tree must be atomically open or + // closed for reuse to work (after DERBY-827). + + isOpen = true; // to make close do its thing: + try { close(); } catch (StandardException ee) {} + throw e; + } + sorted = true; isOpen = true; Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/GroupedAggregateResultSet.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/GroupedAggregateResultSet.java?rev=804327&r1=804326&r2=804327&view=diff ============================================================================== --- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/GroupedAggregateResultSet.java (original) +++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/GroupedAggregateResultSet.java Fri Aug 14 19:12:46 2009 @@ -158,26 +158,35 @@ source.openCore(); - /* If this is an in-order group by then we do not need the sorter. - * (We can do the aggregation ourselves.) - * We save a clone of the first row so that subsequent next()s - * do not overwrite the saved row. - */ - if (isInSortedOrder) - { - currSortedRow = getNextRowFromRS(); - if (currSortedRow != null) + try { + /* If this is an in-order group by then we do not need the sorter. + * (We can do the aggregation ourselves.) + * We save a clone of the first row so that subsequent next()s + * do not overwrite the saved row. + */ + if (isInSortedOrder) { - currSortedRow = (ExecIndexRow) currSortedRow.getClone(); - initializeVectorAggregation(currSortedRow); + currSortedRow = getNextRowFromRS(); + if (currSortedRow != null) + { + currSortedRow = (ExecIndexRow) currSortedRow.getClone(); + initializeVectorAggregation(currSortedRow); + } } - } - else - { - /* - ** Load up the sorter - */ - scanController = loadSorter(); + else + { + /* + ** Load up the sorter + */ + scanController = loadSorter(); + } + } catch (StandardException e) { + // DERBY-4330 Result set tree must be atomically open or + // closed for reuse to work (after DERBY-827). + + isOpen = true; // to make close do its thing: + try { close(); } catch (StandardException ee) {} + throw e; } isOpen = true; Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/JoinResultSet.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/JoinResultSet.java?rev=804327&r1=804326&r2=804327&view=diff ============================================================================== --- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/JoinResultSet.java (original) +++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/JoinResultSet.java Fri Aug 14 19:12:46 2009 @@ -143,14 +143,25 @@ if (SanityManager.DEBUG) SanityManager.ASSERT( ! isOpen, "JoinResultSet already open"); - isOpen = true; leftResultSet.openCore(); - leftRow = leftResultSet.getNextRowCore(); - if (leftRow != null) - { - openRight(); - rowsSeenLeft++; + + try { + leftRow = leftResultSet.getNextRowCore(); + if (leftRow != null) + { + openRight(); + rowsSeenLeft++; + } + } catch (StandardException e) { + // DERBY-4330 Result set tree must be atomically open or + // closed for reuse to work (after DERBY-827). + + isOpen = true; // to make close work: + try { close(); } catch (StandardException ee) {} + throw e; } + + isOpen = true; numOpens++; openTime += getElapsedMillis(beginTime); Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/SetOpResultSet.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/SetOpResultSet.java?rev=804327&r1=804326&r2=804327&view=diff ============================================================================== --- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/SetOpResultSet.java (original) +++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/SetOpResultSet.java Fri Aug 14 19:12:46 2009 @@ -108,15 +108,25 @@ if (SanityManager.DEBUG) SanityManager.ASSERT( ! isOpen, "SetOpResultSet already open"); - isOpen = true; leftSource.openCore(); - rightSource.openCore(); - rightInputRow = rightSource.getNextRowCore(); + + try { + rightSource.openCore(); + rightInputRow = rightSource.getNextRowCore(); + } catch (StandardException e) { + // DERBY-4330 Result set tree must be atomically open or + // closed for reuse to work (after DERBY-827). + isOpen = true; // to make close work: + try { close(); } catch (StandardException ee) {} + throw e; + } + if (rightInputRow != null) { rowsSeenRight++; } + isOpen = true; numOpens++; openTime += getElapsedMillis(beginTime); Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/SortResultSet.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/SortResultSet.java?rev=804327&r1=804326&r2=804327&view=diff ============================================================================== --- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/SortResultSet.java (original) +++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/SortResultSet.java Fri Aug 14 19:12:46 2009 @@ -247,26 +247,35 @@ source.openCore(); - /* If this is an in-order distinct then we do not need the sorter. - * (We filter out the duplicate rows ourselves.) - * We save a clone of the first row so that subsequent next()s - * do not overwrite the saved row. - */ - if (isInSortedOrder && distinct) - { - currSortedRow = getNextRowFromRS(); - if (currSortedRow != null) + try { + /* If this is an in-order distinct then we do not need the sorter. + * (We filter out the duplicate rows ourselves.) We save a clone + * of the first row so that subsequent next()s do not overwrite the + * saved row. + */ + if (isInSortedOrder && distinct) + { + currSortedRow = getNextRowFromRS(); + + if (currSortedRow != null) + { + currSortedRow = (ExecRow) currSortedRow.getClone(); + } + } + else { - currSortedRow = (ExecRow) currSortedRow.getClone(); + /* + ** Load up the sorter. + */ + scanController = loadSorter(); + sorted = true; } - } - else - { - /* - ** Load up the sorter. - */ - scanController = loadSorter(); - sorted = true; + } catch (StandardException e) { + // DERBY-4330 Result set tree must be atomically open or + // closed for reuse to work (after DERBY-827). + isOpen = true; // to make close do its thing: + try { close(); } catch (StandardException ee) {} + throw e; } isOpen = true; Modified: db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/UnionResultSet.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/UnionResultSet.java?rev=804327&r1=804326&r2=804327&view=diff ============================================================================== --- db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/UnionResultSet.java (original) +++ db/derby/code/branches/10.4/java/engine/org/apache/derby/impl/sql/execute/UnionResultSet.java Fri Aug 14 19:12:46 2009 @@ -99,8 +99,8 @@ if (SanityManager.DEBUG) SanityManager.ASSERT( ! isOpen, "UnionResultSet already open"); - isOpen = true; source1.openCore(); + isOpen = true; numOpens++; openTime += getElapsedMillis(beginTime); Modified: db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ResultSetsFromPreparedStatementTest.java URL: http://svn.apache.org/viewvc/db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ResultSetsFromPreparedStatementTest.java?rev=804327&r1=804326&r2=804327&view=diff ============================================================================== --- db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ResultSetsFromPreparedStatementTest.java (original) +++ db/derby/code/branches/10.4/java/testing/org/apache/derbyTesting/functionTests/tests/lang/ResultSetsFromPreparedStatementTest.java Fri Aug 14 19:12:46 2009 @@ -167,6 +167,10 @@ /** Secondary connection. Used if something needs to be executed in a * separate transaction. */ private Connection c2; + private Connection c3; + + + private static final long DERBY_DEFAULT_TIMEOUT = 60; /** * Creates a String containing an insert statement for the @@ -452,6 +456,31 @@ try { s.executeUpdate("drop table emp"); } catch (SQLException e) {} try { s.executeUpdate("drop table emp2"); } catch (SQLException e) {} try { s.executeUpdate("drop table dept"); } catch (SQLException e) {} + + // DERBY-4330 tables: + try { + if (c3 != null && !c3.isClosed()) { + c3.rollback(); + c3.close(); + } + } catch (SQLException e) { + } + + try { s.executeUpdate( + "drop table APP.FILECHANGES"); } catch (SQLException e) {} + try { s.executeUpdate( + "drop table APP.CHANGESETS"); } catch (SQLException e) {} + try { s.executeUpdate( + "drop table APP.AUTHORS"); } catch (SQLException e) {} + try { s.executeUpdate( + "drop table APP.FILES"); } catch (SQLException e) {} + try { s.executeUpdate( + "drop table APP.REPOSITORIES"); } catch (SQLException e) {} + try { s.executeUpdate( + "drop table APP.FILECHANGES_2"); } catch (SQLException e) {} + + try { setTimeout(DERBY_DEFAULT_TIMEOUT); } catch (SQLException e) {} + s.close(); commit(); @@ -2132,4 +2161,364 @@ ps.setMaxRows(2); JDBC.assertDrainResults(ps.executeQuery(), 2); } + + public void testDerby4330_JoinResultSet() throws SQLException { + setTimeout(1); + setSchema("APP"); + createDerby4330_join_tables(); + + PreparedStatement ps = prepareStatement( + "SELECT CS.REVISION, A.NAME, CS.TIME, CS.MESSAGE, F.PATH " + + "FROM " + + "CHANGESETS CS, FILECHANGES FC, " + + " REPOSITORIES R, FILES F, AUTHORS A " + + "WHERE " + + "F.REPOSITORY = R.ID AND A.REPOSITORY = R.ID AND " + + "CS.REPOSITORY = R.ID AND CS.ID = FC.CHANGESET AND " + + "F.ID = FC.FILE AND A.ID = CS.AUTHOR AND " + + "EXISTS ( " + + "SELECT 1 " + + "FROM FILES F2 " + + "WHERE " + + "F2.ID = FC.FILE AND F2.REPOSITORY = R.ID) " + + "ORDER BY CS.ID DESC"); + + c3 = openDefaultConnection(); + c3.setAutoCommit(false); + Statement stm2 = c3.createStatement(); + stm2.execute("LOCK TABLE FILECHANGES IN EXCLUSIVE MODE"); + stm2.close(); + + try { + ps.executeQuery(); + fail(); + } catch (SQLException e) { + assertSQLState("Expected timeout", "40XL1", e); + } + + c3.rollback(); + c3.close(); + + ResultSet rs = ps.executeQuery(); + assertTrue(rs.next()); + assertEquals(rs.getString(2), "xyz"); // name + assertFalse(rs.next()); + ps.close(); + + } + + + public void testDerby4330_UnionResultSet() throws SQLException { + setTimeout(1); + setSchema("APP"); + createDerby4330_union_tables(); + + PreparedStatement ps = prepareStatement( + "SELECT * FROM (" + + "SELECT * FROM FILECHANGES_2 UNION " + + "SELECT * FROM FILECHANGES) X"); // locked file last + + PreparedStatement ps_inverse = prepareStatement( + "SELECT * FROM (" + + "SELECT * FROM FILECHANGES UNION " + // locked file first + "SELECT * FROM FILECHANGES_2) X"); + + c3 = openDefaultConnection(); + c3.setAutoCommit(false); + Statement stm2 = c3.createStatement(); + stm2.execute("LOCK TABLE FILECHANGES IN EXCLUSIVE MODE"); + stm2.close(); + + try { + ps.executeQuery(); + fail(); + } catch (SQLException e) { + assertSQLState("Expected timeout", "40XL1", e); + } + + try { + ps_inverse.executeQuery(); + fail(); + } catch (SQLException e) { + assertSQLState("Expected timeout", "40XL1", e); + } + + c3.rollback(); + c3.close(); + + ResultSet rs = ps.executeQuery(); + JDBC.assertFullResultSet(rs, new String[][]{{"1", "1", "1"}}); + + rs = ps_inverse.executeQuery(); + JDBC.assertFullResultSet(rs, new String[][]{{"1", "1", "1"}}); + + ps.close(); + ps_inverse.close(); + + } + + + public void testDerby4330_SetOpResultSet() throws SQLException { + setTimeout(1); + setSchema("APP"); + createDerby4330_union_tables(); + + String[] ops = {"EXCEPT", "INTERSECT"}; + String[][][] opExpectedRs = {null, {{"1", "1", "1"}}}; + + for (int i=0; i < 2; i++) { + PreparedStatement ps = prepareStatement( + "SELECT * FROM (" + + "SELECT * FROM FILECHANGES_2 " + ops[i] + " " + + // locked file last + "SELECT * FROM FILECHANGES) X ORDER BY ID"); + + PreparedStatement ps_inverse = prepareStatement( + "SELECT * FROM (" + + // locked file first: + "SELECT * FROM FILECHANGES " + ops[i] + " " + + "SELECT * FROM FILECHANGES_2) X ORDER BY ID"); + + c3 = openDefaultConnection(); + c3.setAutoCommit(false); + Statement stm2 = c3.createStatement(); + stm2.execute("LOCK TABLE FILECHANGES IN EXCLUSIVE MODE"); + stm2.close(); + + try { + ps.executeQuery(); + fail(); + } catch (SQLException e) { + assertSQLState("Expected timeout", "40XL1", e); + } + + try { + ps_inverse.executeQuery(); + fail(); + } catch (SQLException e) { + assertSQLState("Expected timeout", "40XL1", e); + } + + c3.rollback(); + c3.close(); + + ResultSet rs = ps.executeQuery(); + + if (opExpectedRs[i] != null) { + JDBC.assertFullResultSet(rs, opExpectedRs[i]); + } else { + JDBC.assertEmpty(rs); + } + + rs = ps_inverse.executeQuery(); + + if (opExpectedRs[i] != null) { + JDBC.assertFullResultSet(rs, opExpectedRs[i]); + } else { + JDBC.assertEmpty(rs); + } + + ps.close(); + ps_inverse.close(); + + } + + } + + + public void testDerby4330_GroupedAggregateResultSet() throws SQLException { + setTimeout(1); + setSchema("APP"); + createDerby4330_union_tables(); + + PreparedStatement ps = prepareStatement( + "SELECT SUM(CHANGESET) from FILECHANGES GROUP BY FILE"); + + c3 = openDefaultConnection(); + c3.setAutoCommit(false); + Statement stm2 = c3.createStatement(); + // Next statement gives an exclusive write lock on a row in FILECHANGES: + stm2.execute("INSERT INTO FILECHANGES(FILE,CHANGESET) VALUES (2,2)"); + stm2.close(); + + try { + ps.executeQuery(); + fail(); + } catch (SQLException e) { + assertSQLState("Expected timeout", "40XL1", e); + } + + c3.rollback(); + c3.close(); + + ResultSet rs = ps.executeQuery(); + JDBC.assertFullResultSet(rs, new String[][]{{"1"}}); + + ps.close(); + } + + + public void testDerby4330_DistinctGroupedAggregateResultSet() + throws SQLException + { + setTimeout(1); + setSchema("APP"); + createDerby4330_union_tables(); + + PreparedStatement ps = prepareStatement( + "SELECT SUM(DISTINCT CHANGESET) from FILECHANGES GROUP BY FILE"); + + c3 = openDefaultConnection(); + c3.setAutoCommit(false); + Statement stm2 = c3.createStatement(); + // Next statement gives an exclusive write lock on a row in FILECHANGES: + stm2.execute("INSERT INTO FILECHANGES(FILE,CHANGESET) VALUES (2,2)"); + stm2.close(); + + try { + ps.executeQuery(); + fail(); + } catch (SQLException e) { + assertSQLState("Expected timeout", "40XL1", e); + } + + c3.rollback(); + c3.close(); + + ResultSet rs = ps.executeQuery(); + JDBC.assertFullResultSet(rs, new String[][]{{"1"}}); + + ps.close(); + } + + + public void testDerby4330_DistinctScalarAggregateResultSet() + throws SQLException + { + setTimeout(1); + setSchema("APP"); + createDerby4330_union_tables(); + + PreparedStatement ps = prepareStatement( + "SELECT SUM(DISTINCT CHANGESET) from FILECHANGES"); + + c3 = openDefaultConnection(); + c3.setAutoCommit(false); + Statement stm2 = c3.createStatement(); + // Next statement gives an exclusive write lock on a row in FILECHANGES: + stm2.execute("INSERT INTO FILECHANGES(FILE,CHANGESET) VALUES (2,2)"); + stm2.close(); + + try { + ps.executeQuery(); + fail(); + } catch (SQLException e) { + assertSQLState("Expected timeout", "40XL1", e); + } + + c3.rollback(); + c3.close(); + + ResultSet rs = ps.executeQuery(); + JDBC.assertFullResultSet(rs, new String[][]{{"1"}}); + + ps.close(); + } + + + private void setTimeout(long t) throws SQLException { + Statement stm = createStatement(); + stm.execute("call syscs_util.syscs_set_database_property(" + + "'derby.locks.waitTimeout', '" + t + "')"); + stm.close(); + } + + + private void createDerby4330_join_tables() throws SQLException { + Statement stm = createStatement(); + stm.execute( + "CREATE TABLE REPOSITORIES (" + + "ID INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY," + + "PATH VARCHAR(32672) UNIQUE NOT NULL)"); + + stm.execute( + "INSERT INTO REPOSITORIES(PATH) VALUES ('r')"); + + stm.execute( + "CREATE TABLE FILES (" + + "ID INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY," + + "PATH VARCHAR(32672) NOT NULL," + + "REPOSITORY INT NOT NULL REFERENCES REPOSITORIES" + + " ON DELETE CASCADE," + + "UNIQUE (REPOSITORY, PATH))"); + + stm.execute( + "INSERT INTO FILES(PATH, REPOSITORY) VALUES ('/adsf',1)"); + + stm.execute( + "CREATE TABLE AUTHORS (" + + "ID INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY," + + "REPOSITORY INT NOT NULL REFERENCES REPOSITORIES " + + " ON DELETE CASCADE," + + "NAME VARCHAR(32672) NOT NULL," + + "UNIQUE (REPOSITORY, NAME))"); + + stm.execute( + "INSERT INTO AUTHORS(REPOSITORY, NAME) VALUES (1, 'xyz')"); + + stm.execute( + "CREATE TABLE CHANGESETS (" + + "ID INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY," + + "REPOSITORY INT NOT NULL REFERENCES REPOSITORIES " + + " ON DELETE CASCADE," + + "REVISION VARCHAR(1024) NOT NULL," + + "AUTHOR INT NOT NULL REFERENCES AUTHORS ON DELETE CASCADE," + + "TIME TIMESTAMP NOT NULL," + + "MESSAGE VARCHAR(32672) NOT NULL," + + "UNIQUE (REPOSITORY, REVISION))"); + + stm.execute( + "INSERT INTO CHANGESETS(REPOSITORY, REVISION, " + + " AUTHOR, TIME, MESSAGE)" + + " VALUES (1,'',1,CURRENT_TIMESTAMP,'')"); + + stm.execute( + "CREATE TABLE FILECHANGES (" + + "ID INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY," + + "FILE INT NOT NULL REFERENCES FILES ON DELETE CASCADE," + + "CHANGESET INT NOT NULL REFERENCES CHANGESETS ON DELETE CASCADE," + + "UNIQUE (FILE, CHANGESET))"); + + stm.execute("INSERT INTO FILECHANGES(FILE,CHANGESET) VALUES (1,1)"); + stm.close(); + commit(); + } + + + private void createDerby4330_union_tables() throws SQLException { + Statement stm = createStatement(); + stm.execute("CREATE TABLE FILECHANGES (" + + "ID INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY," + + "FILE INT NOT NULL," + + "CHANGESET INT NOT NULL," + + "UNIQUE (FILE, CHANGESET))"); + + stm.execute("CREATE TABLE FILECHANGES_2 (" + + "ID INT PRIMARY KEY GENERATED ALWAYS AS IDENTITY," + + "FILE INT NOT NULL," + + "CHANGESET INT NOT NULL," + + "UNIQUE (FILE, CHANGESET))"); + + stm.execute("INSERT INTO FILECHANGES(FILE,CHANGESET) VALUES (1,1)"); + stm.execute("INSERT INTO FILECHANGES_2(FILE,CHANGESET) VALUES (1,1)"); + stm.close(); + commit(); + } + + + private void setSchema(String schema) throws SQLException { + Statement stm = createStatement(); + stm.execute("SET SCHEMA " + schema); + stm.close(); + } }