persistence@glassfish.java.net

Re: Code Review for Issue 2476 Incorrect ddl generated for 2 UniqueConstraints on same table with MSSql

From: Wonseok Kim <guruwons_at_gmail.com>
Date: Fri, 18 May 2007 01:07:29 +0900

Hi Tom,

I couldn't bring up a general test case because when table name is too long,
it fails even in creating the table and it cannot run on any platform due to
the platform-dependent maximum length of identifier(128 for Derby, 30 for
Oracle, right?). The maximum size of unique key name(or field name) for SQL
Server is set as 22 in platform class, but table name can be much longer as
you can see in the issue description, so this problem could arise.

I tested the modified method by making real non-automated :) unit test
against the method to confirm the behavior.

To test this kind of problem well, I think either pure unit test or mock
database platform would be helpful, but there hasn't been such a test so
far.

Thanks,
-Wonseok

On 5/17/07, Tom Ware <tom.ware_at_oracle.com> wrote:
>
> Hi Wonseok,
>
> The code looks good.
>
> Were you able to recreate the problem on a non SQL Server database by
> either making the names really long or by temporarily shortening the
> allowable lengths? If so, do you think this would make a good test case?
>
> -Tom
>
> Wonseok Kim wrote:
>
> > Hi Tom,
> >
> > These days I've been really busy on my original job, but I had some
> > time to fix this issue. :-)
> > https://glassfish.dev.java.net/issues/show_bug.cgi?id=2476
> > <https://glassfish.dev.java.net/issues/show_bug.cgi?id=2476>
> >
> > The logic of generating unique constraint key name had problem of
> > truncating sequence number which is appended to table name, therefore
> > if the table name is long and there are more than one unique
> > constraints this problem could occur in any database. I fixed this
> > similar to the logic of generating foreign key constraint
> > name(buildForeignKeyConstraintName method).
> >
> > Please see below diff.
> > With this fix there was no failure in the existing entity persistence
> > tests and I confirmed that unique constraint names are generated
> > always with sequence number with my local test. But I could not run
> > the test against MS SQL Server because I don't have a machine now
> > where SQL Server is installed.
> >
> > Thanks,
> > -Wonseok
> >
> > Index:
> >
> src/java/oracle/toplink/essentials/tools/schemaframework/DefaultTableGenerator.java
> > ===================================================================
> > RCS file:
> >
> /cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/tools/schemaframework/DefaultTableGenerator.java,v
> > retrieving revision 1.16
> > diff -c -w -r1.16 DefaultTableGenerator.java
> > ***
> >
> src/java/oracle/toplink/essentials/tools/schemaframework/DefaultTableGenerator.java
> > 6 May 2007 02:17:06 -0000 1.16
> > ---
> >
> src/java/oracle/toplink/essentials/tools/schemaframework/DefaultTableGenerator.java
> > 17 May 2007 08:51:01 -0000
> > ***************
> > *** 742,748 ****
> > UniqueKeyConstraint uniqueKeyConstraint;
> > int serialNumber = 0;
> > for (String[] uniqueConstraint : uniqueConstraints) {
> > ! if(uniqueConstraint.length == 0) continue;
> > uniqueKeyConstraint =
> > sourceTableDef.buildUniqueKeyConstraint(uniqueConstraint,
> > serialNumber++, databasePlatform);
> > sourceTableDef.addUniqueKeyConstraint(uniqueKeyConstraint);
> > }
> > --- 742,748 ----
> > UniqueKeyConstraint uniqueKeyConstraint;
> > int serialNumber = 0;
> > for (String[] uniqueConstraint : uniqueConstraints) {
> > ! if(uniqueConstraint == null || uniqueConstraint.length
> > == 0) continue;
> > uniqueKeyConstraint =
> > sourceTableDef.buildUniqueKeyConstraint(uniqueConstraint,
> > serialNumber++, databasePlatform);
> > sourceTableDef.addUniqueKeyConstraint
> (uniqueKeyConstraint);
> > }
> > Index:
> >
> src/java/oracle/toplink/essentials/tools/schemaframework/TableDefinition.java
> > ===================================================================
> > RCS file:
> >
> /cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/tools/schemaframework/TableDefinition.java,v
> > retrieving revision 1.10
> > diff -c -w -r1.10 TableDefinition.java
> > ***
> >
> src/java/oracle/toplink/essentials/tools/schemaframework/TableDefinition.java
> > 6 May 2007 02:17:06 -0000 1.10
> > ---
> >
> src/java/oracle/toplink/essentials/tools/schemaframework/TableDefinition.java
> > 17 May 2007 08:51:01 -0000
> > ***************
> > *** 479,489 ****
> > }
> >
> > /**
> > ! * Return unique key constraint name built from the table and
> > field name with the specified maximum length. To
> > ! * make the name short enough we
> > * 1. Drop the "UNQ_" prefix.
> > * 2. Drop the underscore characters if any.
> > ! * 3. Drop the vowels from the table and field name.
> > * 4. Truncate the table name to zero length if necessary.
> > */
> > protected String buildUniqueKeyConstraintName(String tableName,
> > int serialNumber, int maximumNameLength) {
> > --- 479,489 ----
> > }
> >
> > /**
> > ! * Return unique key constraint name built from the table name
> > and sequence
> > ! * number with the specified maximum length. To make the name
> > short enough we
> > * 1. Drop the "UNQ_" prefix.
> > * 2. Drop the underscore characters if any.
> > ! * 3. Drop the vowels from the table name.
> > * 4. Truncate the table name to zero length if necessary.
> > */
> > protected String buildUniqueKeyConstraintName(String tableName,
> > int serialNumber, int maximumNameLength) {
> > ***************
> > *** 495,507 ****
> > // Still too long: remove the underscore characters
> > uniqueKeyName =
> > Helper.removeAllButAlphaNumericToFit(tableName + serialNumber,
> > maximumNameLength);
> > if (uniqueKeyName.length() > maximumNameLength) {
> > ! // Still too long: remove vowels from the table
> > name and field name.
> > String onlyAlphaNumericTableName =
> > Helper.removeAllButAlphaNumericToFit(tableName, 0);
> > ! uniqueKeyName =
> > Helper.shortenStringsByRemovingVowelsToFit (onlyAlphaNumericTableName,
> > "", maximumNameLength);
> > if (uniqueKeyName.length() > maximumNameLength) {
> > ! // Still too long: remove vowels from the
> > table name and field name and truncate the table name.
> > String shortenedTableName =
> > Helper.removeVowels(onlyAlphaNumericTableName);
> > ! uniqueKeyName =
> > Helper.truncate(shortenedTableName, maximumNameLength -
> > shortenedTableName.length());
> > }
> > }
> > }
> > --- 495,508 ----
> > // Still too long: remove the underscore characters
> > uniqueKeyName =
> > Helper.removeAllButAlphaNumericToFit(tableName + serialNumber,
> > maximumNameLength);
> > if (uniqueKeyName.length() > maximumNameLength) {
> > ! // Still too long: remove vowels from the table
> > name
> > String onlyAlphaNumericTableName =
> > Helper.removeAllButAlphaNumericToFit(tableName, 0);
> > ! String serialName = String.valueOf(serialNumber);
> > ! uniqueKeyName =
> > Helper.shortenStringsByRemovingVowelsToFit(onlyAlphaNumericTableName,
> > serialName, maximumNameLength);
> > if (uniqueKeyName.length() > maximumNameLength) {
> > ! // Still too long: remove vowels from the
> > table name and truncate the table name.
> > String shortenedTableName =
> > Helper.removeVowels(onlyAlphaNumericTableName);
> > ! uniqueKeyName =
> > Helper.truncate(shortenedTableName, maximumNameLength -
> > serialName.length()) + serialName;
> > }
> > }
> > }
> >
>