Return-Path: X-Original-To: apmail-db-derby-commits-archive@www.apache.org Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id 95C0B75CE for ; Thu, 22 Sep 2011 22:49:22 +0000 (UTC) Received: (qmail 49317 invoked by uid 500); 22 Sep 2011 22:49:22 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 49297 invoked by uid 500); 22 Sep 2011 22:49:22 -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 49290 invoked by uid 99); 22 Sep 2011 22:49:22 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 22 Sep 2011 22:49:22 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.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; Thu, 22 Sep 2011 22:49:20 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 4555723888E4; Thu, 22 Sep 2011 22:49:00 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1174436 - in /db/derby/code/trunk/java: engine/org/apache/derby/impl/store/access/btree/ engine/org/apache/derby/impl/store/access/btree/index/ engine/org/apache/derby/impl/store/access/conglomerate/ engine/org/apache/derby/impl/store/acce... Date: Thu, 22 Sep 2011 22:48:59 -0000 To: derby-commits@db.apache.org From: kristwaa@apache.org X-Mailer: svnmailer-1.0.8-patched Message-Id: <20110922224900.4555723888E4@eris.apache.org> Author: kristwaa Date: Thu Sep 22 22:48:59 2011 New Revision: 1174436 URL: http://svn.apache.org/viewvc?rev=1174436&view=rev Log: DERBY-5367: Stale data retrieved when using new collation=TERRITORY_BASED:PRIMARY feature Deoptimize code path for BTree insert when updating columns with a collation different from UCS BASIC. Simply undeleting the existing matching row (marked as deleted) may be incorrect, because the value stored there can be different from the key value used for lookup due to the collation. Added code to track whether a conglomerate contains a collated column or not, such that the right insert code path can be chosen. The array of collation ids is scanned when a conglomerate is created, and when a conglomerate is "restored" from disk (i.e. readExternal). Added a test for the new code path (based on the issue report). Patch file: derby-5367-4c-fix_with_optimization_improved.diff Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/BTree.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/OpenBTree.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/index/B2I.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/ConglomerateUtil.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/GenericConglomerate.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerate.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerateScratchSpace.java db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/Heap.java db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/CollationTest2.java Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/BTree.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/BTree.java?rev=1174436&r1=1174435&r2=1174436&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/BTree.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/BTree.java Thu Sep 22 22:48:59 2011 @@ -57,8 +57,6 @@ import java.io.ObjectInput; import java.util.Properties; -import org.apache.derby.iapi.services.io.ArrayUtil; - /** A b-tree object corresponds to an instance of a b-tree conglomerate. It @@ -192,6 +190,11 @@ public abstract class BTree extends Gene The array of collation id's for each column in the template. **/ protected int[] collation_ids; + /** + * Tells if there is at least one column in the conglomerate whose collation + * isn't StringDataValue.COLLATION_TYPE_UCS_BASIC. + */ + protected boolean hasCollatedTypes; /* @@ -586,7 +589,8 @@ public abstract class BTree extends Gene public DynamicCompiledOpenConglomInfo getDynamicCompiledConglomInfo() throws StandardException { - return(new OpenConglomerateScratchSpace(format_ids, collation_ids)); + return(new OpenConglomerateScratchSpace( + format_ids, collation_ids, hasCollatedTypes)); } Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java?rev=1174436&r1=1174435&r2=1174436&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/BTreeController.java Thu Sep 22 22:48:59 2011 @@ -51,7 +51,6 @@ import org.apache.derby.iapi.types.RowLo import org.apache.derby.iapi.services.io.FormatableBitSet; import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil; -import org.apache.derby.impl.store.access.conglomerate.TemplateRow; /** @@ -845,17 +844,44 @@ public class BTreeController extends Ope insert_slot, false, this.btree_undo); boolean update_succeeded = true; - try { - int rowloc_index = - this.getConglomerate().nKeyFields - 1; - targetleaf.page.updateFieldAtSlot( - insert_slot, rowloc_index, - (DataValueDescriptor) RowUtil.getColumn( - rowToInsert, - (FormatableBitSet) null, rowloc_index), - this.btree_undo); + if (runtime_mem.hasCollatedTypes()) + { + // See DERBY-5367. + // There are types in the BTree with a + // collation different than UCS BASIC, we + // update all fields to make sure they hold + // the correct values. + // NOTE: We could optimize here by only + // updating the fields that actually hold + // collated types. + int rowsToUpdate = getConglomerate().nKeyFields; + for (int i=0; i < rowsToUpdate; i++) { + targetleaf.page.updateFieldAtSlot( + insert_slot, i, + (DataValueDescriptor) RowUtil.getColumn( + rowToInsert, + (FormatableBitSet) null, i), + this.btree_undo); + } + } + else + { + // There are no collated types in the BTree, + // which means that the values currently + // stored in the undeleted row are correct. + // We simply update the row location to point + // to the correct row in the heap. + int rowloc_index = + this.getConglomerate().nKeyFields - 1; + targetleaf.page.updateFieldAtSlot( + insert_slot, rowloc_index, + (DataValueDescriptor) RowUtil.getColumn( + rowToInsert, + (FormatableBitSet) null, rowloc_index), + this.btree_undo); + } } catch (StandardException se) { Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/OpenBTree.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/OpenBTree.java?rev=1174436&r1=1174435&r2=1174436&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/OpenBTree.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/OpenBTree.java Thu Sep 22 22:48:59 2011 @@ -34,7 +34,6 @@ import org.apache.derby.iapi.store.acces import org.apache.derby.iapi.store.access.SpaceInfo; import org.apache.derby.iapi.store.raw.ContainerHandle; import org.apache.derby.iapi.store.raw.LockingPolicy; -import org.apache.derby.iapi.store.raw.RecordHandle; import org.apache.derby.iapi.store.raw.Transaction; import org.apache.derby.iapi.types.DataValueDescriptor; @@ -91,7 +90,6 @@ public class OpenBTree **/ protected int init_lock_level; - private DynamicCompiledOpenConglomInfo init_dynamic_info; private boolean init_hold; /** @@ -414,8 +412,6 @@ public class OpenBTree // Isolation level of this btree. init_lock_level = lock_level; - init_dynamic_info = dynamic_info; - init_hold = hold; @@ -429,9 +425,8 @@ public class OpenBTree this.runtime_mem = (dynamic_info != null ? ((OpenConglomerateScratchSpace) dynamic_info) : - new OpenConglomerateScratchSpace( - conglomerate.format_ids, - conglomerate.collation_ids)); + (OpenConglomerateScratchSpace) + conglomerate.getDynamicCompiledConglomInfo()); } Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/index/B2I.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/index/B2I.java?rev=1174436&r1=1174435&r2=1174436&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/index/B2I.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/btree/index/B2I.java Thu Sep 22 22:48:59 2011 @@ -29,12 +29,9 @@ import java.util.Properties; import org.apache.derby.iapi.reference.SQLState; import org.apache.derby.iapi.services.io.ArrayInputStream; -import org.apache.derby.iapi.services.io.FormatableBitSet; import org.apache.derby.iapi.services.sanity.SanityManager; import org.apache.derby.iapi.error.StandardException; -import org.apache.derby.iapi.store.raw.Page; -import org.apache.derby.impl.store.access.btree.ControlRow; import org.apache.derby.impl.store.access.conglomerate.ConglomerateUtil; import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo; @@ -66,7 +63,6 @@ import org.apache.derby.impl.store.acces import org.apache.derby.iapi.services.cache.ClassSize; -import org.apache.derby.iapi.services.io.CompressedNumber; import org.apache.derby.iapi.services.io.FormatableBitSet; import org.apache.derby.iapi.services.io.StoredFormatIds; @@ -596,6 +592,7 @@ public class B2I extends BTree // conglom state. collation_ids = ConglomerateUtil.createCollationIds(template.length, collationIds); + hasCollatedTypes = hasCollatedColumns(collation_ids); // Do the generic part of creating the b-tree. super.create( @@ -1156,6 +1153,9 @@ public class B2I extends BTree // In memory maintain a collation id per column in the template. collation_ids = new int[format_ids.length]; + if (SanityManager.DEBUG) { + SanityManager.ASSERT(!hasCollatedTypes); + } // initialize all the entries to COLLATION_TYPE_UCS_BASIC, // and then reset as necessary. For version ACCESS_B2I_V3_ID, @@ -1181,7 +1181,8 @@ public class B2I extends BTree "length = " + collation_ids.length); } - ConglomerateUtil.readCollationIdArray(collation_ids, in); + hasCollatedTypes = + ConglomerateUtil.readCollationIdArray(collation_ids, in); } else if (conglom_format_id != StoredFormatIds.ACCESS_B2I_V3_ID) { Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/ConglomerateUtil.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/ConglomerateUtil.java?rev=1174436&r1=1174435&r2=1174436&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/ConglomerateUtil.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/ConglomerateUtil.java Thu Sep 22 22:48:59 2011 @@ -28,7 +28,6 @@ import org.apache.derby.iapi.services.io import org.apache.derby.iapi.services.io.Formatable; import org.apache.derby.iapi.services.io.FormatIdUtil; -import org.apache.derby.iapi.store.access.ColumnOrdering; import org.apache.derby.iapi.store.access.RowUtil; import org.apache.derby.iapi.store.raw.FetchDescriptor; @@ -310,9 +309,11 @@ public final class ConglomerateUtil * the sparse array from the stream. * * @param in The stream to read the collation info from. + * @return {@code true} if at least one column has a different collation + * than UCS BASIC, {@code false} otherwise. * **/ - public static void readCollationIdArray( + public static boolean readCollationIdArray( int[] collation_id_array, ObjectInput in) throws IOException @@ -332,6 +333,7 @@ public final class ConglomerateUtil int array_index = CompressedNumber.readInt(in); collation_id_array[array_index] = CompressedNumber.readInt(in); } + return num_compressed_entries > 0; } /** Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/GenericConglomerate.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/GenericConglomerate.java?rev=1174436&r1=1174435&r2=1174436&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/GenericConglomerate.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/GenericConglomerate.java Thu Sep 22 22:48:59 2011 @@ -30,8 +30,8 @@ import org.apache.derby.iapi.error.Stand import org.apache.derby.iapi.store.access.conglomerate.Conglomerate; import org.apache.derby.iapi.types.DataValueDescriptor; - import org.apache.derby.iapi.types.DataType; +import org.apache.derby.iapi.types.StringDataValue; import java.sql.ResultSet; import java.sql.SQLException; @@ -210,4 +210,20 @@ public abstract class GenericConglomerat throw(StandardException.newException( SQLState.HEAP_UNIMPLEMENTED_FEATURE)); } + + /** + * Tells if there are columns with collations (other than UCS BASIC) in the + * given list of collation ids. + * + * @param collationIds collation ids for the conglomerate columns + * @return {@code true} if a collation other than UCS BASIC was found. + */ + public static boolean hasCollatedColumns(int[] collationIds) { + for (int i=0; i < collationIds.length; i++) { + if (collationIds[i] != StringDataValue.COLLATION_TYPE_UCS_BASIC) { + return true; + } + } + return false; + } } Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerate.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerate.java?rev=1174436&r1=1174435&r2=1174436&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerate.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerate.java Thu Sep 22 22:48:59 2011 @@ -876,7 +876,8 @@ public abstract class OpenConglomerate this.runtime_mem = (dynamic_info != null ? ((OpenConglomerateScratchSpace) dynamic_info) : - new OpenConglomerateScratchSpace(format_ids, collation_ids)); + ((OpenConglomerateScratchSpace) + conglomerate.getDynamicCompiledConglomInfo())); // Is this an open for update or read? This will // be passed down to the raw store fetch methods, which allows Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerateScratchSpace.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerateScratchSpace.java?rev=1174436&r1=1174435&r2=1174436&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerateScratchSpace.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/conglomerate/OpenConglomerateScratchSpace.java Thu Sep 22 22:48:59 2011 @@ -32,6 +32,8 @@ import org.apache.derby.iapi.types.DataV import org.apache.derby.iapi.services.io.FormatableBitSet; +import org.apache.derby.iapi.services.sanity.SanityManager; + /** A utility class to store and use temporary scratch space associated with @@ -74,8 +76,15 @@ public class OpenConglomerateScratchSpac /** * A complete array of format id's and collation_ids for this conglomerate. **/ - private int[] format_ids; - private int[] collation_ids; + private final int[] format_ids; + private final int[] collation_ids; + /** + * Tells if there is at least one type in the conglomerate whose collation + * isn't StringDataValue.COLLATION_TYPE_UCS_BASIC. This can be determined + * by looking at the collation ids, but now the caller is passing in the + * value to avoid having to look at all the collation ids multiple times. + */ + private final boolean hasCollatedTypes; /** @@ -96,13 +105,21 @@ public class OpenConglomerateScratchSpac * * @param format_ids format identifiers for columns in the row * @param collation_ids collation identifiers for the columns in the row + * @param hasCollatedTypes whether there is at least one collated type with + * a collation other than UCS BASIC in the conglomerate */ public OpenConglomerateScratchSpace( int[] format_ids, - int[] collation_ids) + int[] collation_ids, + boolean hasCollatedTypes) { this.format_ids = format_ids; this.collation_ids = collation_ids; + this.hasCollatedTypes = hasCollatedTypes; + if (SanityManager.DEBUG) { + SanityManager.ASSERT(GenericConglomerate.hasCollatedColumns( + collation_ids) == hasCollatedTypes); + } } /************************************************************************** @@ -220,4 +237,15 @@ public class OpenConglomerateScratchSpac return(scratch_row_position); } + + /** + * Tells if there is at least one column with a collation different + * than UCS BASIC in the conglomerate. + * + * @return {@code true} if there is at least one column with a collation + * different than UCS BASIC. + */ + public boolean hasCollatedTypes() { + return hasCollatedTypes; + } } Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/Heap.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/Heap.java?rev=1174436&r1=1174435&r2=1174436&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/Heap.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/store/access/heap/Heap.java Thu Sep 22 22:48:59 2011 @@ -42,7 +42,6 @@ import org.apache.derby.iapi.error.Stand import org.apache.derby.iapi.store.access.conglomerate.Conglomerate; import org.apache.derby.iapi.store.access.conglomerate.LogicalUndo; -import org.apache.derby.iapi.store.access.conglomerate.TransactionManager; import org.apache.derby.iapi.store.access.conglomerate.ScanManager; import org.apache.derby.iapi.store.access.conglomerate.TransactionManager; @@ -190,6 +189,11 @@ public class Heap The array of collation id's for each column in the template. **/ protected int[] collation_ids; + /** + * Tells if there is at least one column in the conglomerate whose collation + * isn't StringDataValue.COLLATION_TYPE_UCS_BASIC. + */ + private boolean hasCollatedTypes; private static final int BASE_MEMORY_USAGE = ClassSize.estimateBaseFromCatalog( Heap.class); private static final int CONTAINER_KEY_MEMORY_USAGE = ClassSize.estimateBaseFromCatalog( ContainerKey.class); @@ -305,6 +309,7 @@ public class Heap collation_ids = ConglomerateUtil.createCollationIds( format_ids.length, collationIds); + hasCollatedTypes = hasCollatedColumns(collation_ids); // need to open the container and insert the row. Since we are // creating it no need to bother with locking since no one can get @@ -580,7 +585,8 @@ public class Heap public DynamicCompiledOpenConglomInfo getDynamicCompiledConglomInfo() throws StandardException { - return(new OpenConglomerateScratchSpace(format_ids, collation_ids)); + return(new OpenConglomerateScratchSpace( + format_ids, collation_ids, hasCollatedTypes)); } /** @@ -1202,6 +1208,9 @@ public class Heap // In memory maintain a collation id per column in the template. collation_ids = new int[format_ids.length]; + if (SanityManager.DEBUG) { + SanityManager.ASSERT(!hasCollatedTypes); + } // initialize all the entries to COLLATION_TYPE_UCS_BASIC, // and then reset as necessary. For version ACCESS_HEAP_V2_ID, @@ -1213,7 +1222,8 @@ public class Heap { // current format id, read collation info from disk - ConglomerateUtil.readCollationIdArray(collation_ids, in); + hasCollatedTypes = + ConglomerateUtil.readCollationIdArray(collation_ids, in); } else if (conglom_format_id != StoredFormatIds.ACCESS_HEAP_V2_ID) { Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/CollationTest2.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/CollationTest2.java?rev=1174436&r1=1174435&r2=1174436&view=diff ============================================================================== --- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/CollationTest2.java (original) +++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/lang/CollationTest2.java Thu Sep 22 22:48:59 2011 @@ -34,25 +34,17 @@ import java.text.RuleBasedCollator; import java.util.Locale; import java.util.Properties; -import javax.sql.DataSource; - import junit.framework.Assert; import junit.framework.Test; import junit.framework.TestSuite; import org.apache.derbyTesting.junit.BaseJDBCTestCase; -import org.apache.derbyTesting.junit.DatabasePropertyTestSetup; import org.apache.derbyTesting.junit.Decorator; import org.apache.derbyTesting.junit.JDBC; -import org.apache.derbyTesting.junit.JDBCDataSource; import org.apache.derbyTesting.junit.SystemPropertyTestSetup; import org.apache.derbyTesting.junit.SupportFilesSetup; -import org.apache.derbyTesting.junit.SQLUtilities; import org.apache.derbyTesting.junit.TestConfiguration; -import org.apache.derby.iapi.services.sanity.SanityManager; - - /** Junit test targeted at testing language based Collation. @@ -94,6 +86,10 @@ T24: (DONE) DERBY-2669 If no territory a of Database. +

+NOTE: The prefix "ci_test" is used for tests that require a case insensitive + collation order. + **/ public class CollationTest2 extends BaseJDBCTestCase @@ -902,6 +898,55 @@ public class CollationTest2 extends Base dropTable(); } + /** + * Tests that DERBY-5367 is fixed, a bug where updating the index in a + * database with a case insensitive collation resulted in data corruption. + *

+ * The bug tested is where a deleted row with an incorrect key value in + * the index is undeleted as an optimized insert. In this case it was + * caused by the a case insensitive collation order, but other collation + * rules could cause this to happen as well. + */ + public void ci_testDerby5367() + throws SQLException { + assertFalse(isDatabaseBasicCollation()); + setAutoCommit(true); + String TABLE = "DERBY_5367"; + Statement stmt = createStatement(); + stmt.executeUpdate("create table " + TABLE + "(" + + "VAL varchar(10) not null unique)"); + + // Run first time when the congloms were newly created. + runDerby5367TestCode(TABLE); + + // Shut down the database, reboot. This will trigger the code to + // read the congloms from disk. + TestConfiguration.getCurrent().shutdownDatabase(); + getConnection(); + + // Run second time, read congloms from disk. + runDerby5367TestCode(TABLE); + dropTable(TABLE); + } + + /** Runs the core code for the DERBY-5367 test. */ + private void runDerby5367TestCode(String table) + throws SQLException { + PreparedStatement sel = prepareStatement("select val from " + table + + " where val = 'Test'"); + PreparedStatement ins = prepareStatement("insert into " + table + + " values ?"); + ins.setString(1, "Test"); + ins.executeUpdate(); + JDBC.assertFullResultSet(sel.executeQuery(), new String[][] {{"Test"}}); + Statement stmt = createStatement(); + stmt.executeUpdate("delete from " + table + " where val = 'Test'"); + ins.setString(1, "test"); + ins.executeUpdate(); + JDBC.assertFullResultSet(sel.executeQuery(), new String[][] {{"test"}}); + stmt.executeUpdate("delete from " + table); + } + /************************************************************************** * Private/Protected tests of This class: ************************************************************************** @@ -1920,6 +1965,7 @@ public class CollationTest2 extends Base TestSuite suite = new TestSuite("CollationTest2"); suite.addTest(new CollationTest2("testDefaultCollation")); suite.addTest(collatedTest("en", "testEnglishCollation")); + suite.addTest(caseInsensitiveCollationSuite()); // Only add tests for other locales if they are in fact supported // by the jvm. @@ -1961,4 +2007,17 @@ public class CollationTest2 extends Base return Decorator.territoryCollatedDatabase( new CollationTest2(fixture), locale); } + + /** + * Returns a suite of tests running with a collation strength resulting + * in case insensitivity. + * + * @return A suite of tests. + */ + private static Test caseInsensitiveCollationSuite() { + TestSuite suite = new TestSuite("Case insensitive specific tests"); + suite.addTest(new CollationTest2("ci_testDerby5367")); + return Decorator.territoryCollatedCaseInsensitiveDatabase( + suite, "en_US"); + } }