persistence@glassfish.java.net

Re: Code changes relevant to Issue 272 : java2db support for UniqueConstraint

From: Pramod Gopinath <Pramod.Gopinath_at_Sun.COM>
Date: Wed, 15 Mar 2006 19:48:09 -0800

Hi Gordon
  Here are the latest files to address this issue. The following files
had to changed compared to what was sent out earlier.
1.EntityMappingsXMLProcessor.java :
   Using the file that you had sent earlier. I had to change the
getUniqueConstraint(), to ensure that we create a String[] of column
names for each UniqueConstraint defined on the table.
  This would make the behavior consistent with what was happening in
EJBAnnotationsProcessor.
  After making this change had to make changes to
processUniqueConstraints() to get the String[] and assign it to the
DatabaseTable.

2. Had to make some more changes to TableDefinition to ensure that I
was creating and dropping the unique constraints directly from the
database connection, if that option is used.

3. Have the changed SequenceProcessor.java that you had provided earlier.

Additionally I changed the entity-persistence-tests and added
uniqueConstraint to CMP3_BUYER. This way this feature would be tested
when the tests are run.

Thanks
Pramod

Gordon Yorke wrote:
> Hello Pramod,
> I really can't review these changes. You have missed updates to SequenceProcessor which I have attached here. Updating EntityMappingsXMLProcessor.java is going to require other classes to change unless you use the attached example and provide a DatabaseTable.addUniqueConstraint(String columnName).
> --Gordon



cvs server: I know nothing about src/java/oracle/toplink/essentials/tools/schemaframework/UniqueKeyConstraint.java

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.4
diff -r1.4 DefaultTableGenerator.java
367a368
> tblDef.setUniqueKeys(dbTbl.getUniqueConstraints());
Index: src/java/oracle/toplink/essentials/tools/schemaframework/SchemaManager.java
===================================================================
RCS file: /cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/tools/schemaframework/SchemaManager.java,v
retrieving revision 1.8
diff -r1.8 SchemaManager.java
141a142
> tableDefinition.setCreateSQLFiles(createSQLFiles);
383a385
> tableDefinition.setCreateSQLFiles(createSQLFiles);
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.2
diff -r1.2 TableDefinition.java
38a39
> protected Vector uniqueKeys;
40a42
> private boolean createSQLFiles;
44a47
> this.uniqueKeys = new Vector();
105a109,117
> public void addUniqueKeyConstraint(String name, String sourceField) {
> UniqueKeyConstraint uniqueKey = new UniqueKeyConstraint(name, sourceField);
> addUniqueKeyConstraint(uniqueKey);
> }
>
> /**
> * PUBLIC:
> * Add a foreign key constraint to the table.
> */
109c121,129
<
---
>     
>     /**
>      * PUBLIC:
>      * Add a unique key constraint to the table.
>      */
>     public void addUniqueKeyConstraint(UniqueKeyConstraint uniqueKey) {
>         getUniqueKeys().addElement(uniqueKey);
>     }
>     
200a221,257
>      * Return the alter table statement to add the constraints.
>      * This is done seperatly from the create because of dependecies.
>      */
>     public Writer buildUniqueConstraintCreationWriter(AbstractSession session, UniqueKeyConstraint uniqueKey, Writer writer) throws ValidationException {
>         try {
>             writer.write("ALTER TABLE " + getFullName());
>             writer.write(" ADD CONSTRAINT ");
>             if (!session.getPlatform().shouldPrintConstraintNameAfter()) {
>                 writer.write(uniqueKey.getName() + " ");
>             }
>             uniqueKey.appendDBString(writer, session);
>             if (session.getPlatform().shouldPrintConstraintNameAfter()) {
>                 writer.write(" CONSTRAINT " + uniqueKey.getName());
>             }
>         } catch (IOException ioException) {
>             throw ValidationException.fileError(ioException);
>         }
>         return writer;
>     }
> 
>     /**
>      * INTERNAL:
>      * Return the alter table statement to drop the constraints.
>      * This is done seperatly to allow constraints to be dropped before the tables.
>      */
>     public Writer buildUniqueConstraintDeletionWriter(AbstractSession session, UniqueKeyConstraint uniqueKey, Writer writer) throws ValidationException {
>         try {
>             writer.write("ALTER TABLE " + getFullName());
>             writer.write(session.getPlatform().getConstraintDeletionString() + uniqueKey.getName());
>         } catch (IOException ioException) {
>             throw ValidationException.fileError(ioException);
>         }
>         return writer;
>     }    
> 
>     /**
>      * INTERNAL:
292c349,371
<     protected void buildFieldTypes(AbstractSession session) {
---
>     protected void buildFieldTypes(AbstractSession session) {        
>         buildForeignFieldTypes(session);
>         buildUniqueFieldTypes(session);
>     }
> 
>     private void buildUniqueFieldTypes(final AbstractSession session) {
>         Vector uniqueKeysClone = (Vector)getUniqueKeys().clone();        
>         
>         Object[] uniqueKeysArray = uniqueKeysClone.toArray();
>         setUniqueKeys(new Vector());        
>         UniqueKeyConstraint uniqueKeyConstraint;
>         int serialNumber = 0;
>         for (Object uniqueKeys : uniqueKeysArray) {         
>             uniqueKeyConstraint = buildUniqueKeyConstraint(this, serialNumber++, session.getPlatform());
>             String[] columnNames = (String[])uniqueKeys;
>             for (String columnName : columnNames) {
>                 uniqueKeyConstraint.addSourceField(columnName);
>             }
>             addUniqueKeyConstraint(uniqueKeyConstraint);            
>         }
>     }
> 
>     private void buildForeignFieldTypes(final AbstractSession session) {
295c374,376
<         Vector foreignKeysClone = (Vector)getForeignKeys().clone();
---
>         DatabaseField dbField = null;
>         
>         Vector foreignKeysClone = (Vector)getForeignKeys().clone();          
370a452,489
>     protected UniqueKeyConstraint buildUniqueKeyConstraint(TableDefinition table, int serialNumber, DatabasePlatform platform) {
>         UniqueKeyConstraint unqConstraint = new UniqueKeyConstraint();
>         String tempName = buildUniqueKeyConstraintName(table.getName(), serialNumber, platform.getMaxUniqueKeyNameSize());
>         unqConstraint.setName(tempName);
>         return unqConstraint;
>     }
> 
>     /**
>      * Return foreign 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 "FK_" 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) {
>         String uniqueKeyName = "UNQ_" + tableName + "_" + serialNumber;
>         if (uniqueKeyName.length() > maximumNameLength) {
>             // First Remove the "UNQ_" prefix.
>             uniqueKeyName = tableName;
>             if (uniqueKeyName.length() > maximumNameLength) {
>                 // 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());
>                     }
>                 }
>             }
>         }
>         return uniqueKeyName;
>     }
> 
386a506,508
>         if (uniqueKeys != null) {
>             clone.setUniqueKeys((Vector)uniqueKeys.clone());
>         }        
394c516
<     public void createConstraints(AbstractSession session, Writer schemaWriter) throws TopLinkException {
---
>     public void createConstraints(AbstractSession session, Writer schemaWriter) throws TopLinkException {       
398,402c520,532
<             for (Enumeration foreignKeysEnum = getForeignKeys().elements();
<                      foreignKeysEnum.hasMoreElements();) {
<                 ForeignKeyConstraint foreignKey = (ForeignKeyConstraint)foreignKeysEnum.nextElement();
<                 buildConstraintCreationWriter(session, foreignKey, schemaWriter).toString();
<                 try {
---
>             createForeignConstraints(session, schemaWriter);
>             createUniqueContraints(session, schemaWriter);            
>             
>         }
>     }
> 
>     private void createUniqueContraints(final AbstractSession session, final Writer schemaWriter) throws ValidationException {       
>         for (Enumeration uniqueKeysEnum = getUniqueKeys().elements();
>                  uniqueKeysEnum.hasMoreElements();) {              
>             UniqueKeyConstraint uniqueKey = (UniqueKeyConstraint)uniqueKeysEnum.nextElement();
>             buildUniqueConstraintCreationWriter(session, uniqueKey, schemaWriter).toString();
>             try {
>                 if (createSQLFiles) {
404,406d533
<                     schemaWriter.write("\n");
<                 } catch (IOException exception) {
<                     throw ValidationException.fileError(exception);
407a535,553
>                 schemaWriter.write("\n");
>             } catch (IOException exception) {
>                 throw ValidationException.fileError(exception);
>             }
>         }            
>     }
> 
>     private void createForeignConstraints(final AbstractSession session, final Writer schemaWriter) throws ValidationException {
>         for (Enumeration foreignKeysEnum = getForeignKeys().elements();
>                  foreignKeysEnum.hasMoreElements();) {
>             ForeignKeyConstraint foreignKey = (ForeignKeyConstraint)foreignKeysEnum.nextElement();
>             buildConstraintCreationWriter(session, foreignKey, schemaWriter).toString();
>             try {
>                 if (createSQLFiles){                    
>                     schemaWriter.write(session.getPlatform().getStoredProcedureTerminationToken());
>                 }
>                 schemaWriter.write("\n");
>             } catch (IOException exception) {
>                 throw ValidationException.fileError(exception);
416a563,579
>         createForeignConstraintsOnDatabase(session);
>         createUniqueConstraintsOnDatabase(session);       
>     }
> 
>     private void createUniqueConstraintsOnDatabase(final AbstractSession session) throws ValidationException, DatabaseException {       
>         if ((!session.getPlatform().supportsUniqueKeyConstraints()) || getUniqueKeys().isEmpty()) {
>             return;
>         }
> 
>         for (Enumeration uniqueKeysEnum = getUniqueKeys().elements();
>                  uniqueKeysEnum.hasMoreElements();) {            
>             UniqueKeyConstraint uniqueKey = (UniqueKeyConstraint)uniqueKeysEnum.nextElement();
>             session.executeNonSelectingCall(new oracle.toplink.essentials.queryframework.SQLCall(buildUniqueConstraintCreationWriter(session, uniqueKey, new StringWriter()).toString()));
>         } 
>     }
> 
>     private void createForeignConstraintsOnDatabase(final AbstractSession session) throws ValidationException, DatabaseException {        
449c612,628
<                     schemaWriter.write(session.getPlatform().getStoredProcedureTerminationToken());
---
>                     if (createSQLFiles) {
>                         schemaWriter.write(session.getPlatform().getStoredProcedureTerminationToken());
>                     }
>                     schemaWriter.write("\n");
>                 } catch (IOException exception) {
>                     throw ValidationException.fileError(exception);
>                 }
>             }
>                      
>             for (Enumeration uniqueKeysEnum = getUniqueKeys().elements();
>                      uniqueKeysEnum.hasMoreElements();) {        
>                 UniqueKeyConstraint uniqueKey = (UniqueKeyConstraint)uniqueKeysEnum.nextElement();
>                 buildUniqueConstraintDeletionWriter(session, uniqueKey, schemaWriter).toString();
>                 try {
>                     if (createSQLFiles) {                    
>                         schemaWriter.write(session.getPlatform().getStoredProcedureTerminationToken());
>                     }
464c643,648
<         if ((!session.getPlatform().supportsForeignKeyConstraints()) || getForeignKeys().isEmpty()) {
---
>         dropForeignConstraintsOnDatabase(session);
>         dropUniqueConstraintsOnDatabase(session);        
>     }
> 
>     private void dropUniqueConstraintsOnDatabase(final AbstractSession session) throws ValidationException {        
>         if ((!session.getPlatform().supportsUniqueKeyConstraints()) || getUniqueKeys().isEmpty()) {
466a651,665
>         
>         for (Enumeration uniqueKeysEnum = getUniqueKeys().elements();
>                  uniqueKeysEnum.hasMoreElements();) {
>             UniqueKeyConstraint uniqueKey = (UniqueKeyConstraint)uniqueKeysEnum.nextElement();
>             try {
>                 session.executeNonSelectingCall(new oracle.toplink.essentials.queryframework.SQLCall(buildUniqueConstraintDeletionWriter(session, uniqueKey, new StringWriter()).toString()));
>             } catch (DatabaseException ex) {/* ignore */
>             }
>         }        
>     }
> 
>     private void dropForeignConstraintsOnDatabase(final AbstractSession session) throws ValidationException {        
>         if ((!session.getPlatform().supportsForeignKeyConstraints()) || getForeignKeys().isEmpty()) {
>             return;
>         } 
485a685,688
>     public Vector getUniqueKeys() {
>         return uniqueKeys;
>     }
>     
504a708,715
>     
>     public void setUniqueKeys(Vector uniqueKeys) {
>         this.uniqueKeys = uniqueKeys;
>     }
>     
>     public void setCreateSQLFiles(boolean genFlag) {
>         this.createSQLFiles = genFlag;
>     }    
Index: src/java/oracle/toplink/essentials/internal/annotations/EJBAnnotationsProcessor.java
===================================================================
RCS file: /cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/internal/annotations/EJBAnnotationsProcessor.java,v
retrieving revision 1.22
diff -r1.22 EJBAnnotationsProcessor.java
1737,1740c1737
<             
<             for (String columnName : columnNames) {
<                 table.addUniqueConstraint(new DatabaseField(columnName));
<             }
---
>             table.addUniqueConstraint(columnNames);
Index: src/java/oracle/toplink/essentials/internal/annotations/SequencingProcessor.java
===================================================================
RCS file: /cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/internal/annotations/SequencingProcessor.java,v
retrieving revision 1.6
diff -r1.6 SequencingProcessor.java
392,393c392,393
<             sequence.setTable(new DatabaseTable(MetadataHelper.getFullyQualifiedTableName(tableGenerator.table(), sequence.getTableName(), tableGenerator.catalog(), tableGenerator.schema())));
<             
---
>             sequence.setTable(new DatabaseTable(MetadataHelper.getFullyQualifiedTableName(tableGenerator.table(), sequence.getTableName(), tableGenerator.catalog(), tableGenerator.schema())));            
>               
398,401c398
<             
<                 for (String columnName : columnNames) {
<                     sequence.getTable().addUniqueConstraint(new DatabaseField(columnName));
<                 }
---
>                 sequence.getTable().addUniqueConstraint(columnNames);
Index: src/java/oracle/toplink/essentials/internal/databaseaccess/DatabasePlatform.java
===================================================================
RCS file: /cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/internal/databaseaccess/DatabasePlatform.java,v
retrieving revision 1.8
diff -r1.8 DatabasePlatform.java
693a694,702
>      * returns the maximum number of characters that can be used in a unique key
>      * name on this platform.
>      */
>     public int getMaxUniqueKeyNameSize() {
>         return getMaxFieldNameSize();
>     }    
> 
>     /**
>      * INTERNAL:
1249a1259,1262
>         return true;
>     }
> 
>     public boolean supportsUniqueKeyConstraints() {
Index: src/java/oracle/toplink/essentials/internal/ejb/cmp3/xml/EntityMappingsXMLProcessor.java
===================================================================
RCS file: /cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/internal/ejb/cmp3/xml/EntityMappingsXMLProcessor.java,v
retrieving revision 1.21
diff -r1.21 EntityMappingsXMLProcessor.java
736a737
>         String[] columnNames = {};
745a747
>                 columnNames = new String[columnNameNodeList.getLength()];
751c753
<                             uniqueConstraints[j] = new DatabaseField(columnName);
---
>                             columnNames[k] = columnName;
754a758
>                 uniqueConstraints[j] = columnNames;
2490,2493c2494,2497
<     	// for each constraint
<     	for (int i=0; i<constraints.length; i++) {
<     		dbTable.addUniqueConstraint((DatabaseField) constraints[i]);
<     	}
---
>         for (Object uniqueConstraint : constraints) {
>             String[] columnNames = (String[]) uniqueConstraint;
>             dbTable.addUniqueConstraint(columnNames);
>         }        
Index: src/java/oracle/toplink/essentials/internal/helper/DatabaseTable.java
===================================================================
RCS file: /cvs/glassfish/entity-persistence/src/java/oracle/toplink/essentials/internal/helper/DatabaseTable.java,v
retrieving revision 1.1.1.1
diff -r1.1.1.1 DatabaseTable.java
66,67c66,67
<     public void addUniqueConstraint(DatabaseField uniqueConstraint) {
<         uniqueConstraints.add(uniqueConstraint);
---
>     public void addUniqueConstraint(String[] columnNames) {
>         uniqueConstraints.add(columnNames);