persistence@glassfish.java.net

Code changes relevant to Issue 272 : java2db support for UniqueConstraint

From: Pramod Gopinath <Pramod.Gopinath_at_Sun.COM>
Date: Tue, 14 Mar 2006 17:45:40 -0800

Hi Gordon/Tom
  These are the changes for issue 272 : Support in java2db for
UniqueConstraints

Problems with the existing code:
1. As per the spec the user could provide multiple @UniqueConstraint
annotations for an entity. But the original code was taking the fields
that were part of the unique constraint and storing them into a Vector
in DatabaseTable. This leads to problems at ddl generation type as there
is no way to know which fields belong to which unique constraint.

2. Additionally the existing code was taking each of the field names
that are passed in as part of the UniqueConstraint and creating a
DatabaseField before setting it into the vector. This is not required.
We could take the String[] of columns associated to the UniqueConstraint
and set that as is into the DatabaseTable.

I need help with making changes into this file :
src/java/oracle/toplink/essentials/internal/ejb/cmp3/xml/EntityMappingsXMLProcessor.java

Could U take a look at the method processUniqueConstraints() in this file.


Files Added :
src/java/oracle/toplink/essentials/tools/schemaframework/UniqueKeyConstraint.java


Files Modified :
src/java/oracle/toplink/essentials/internal/annotations/EJBAnnotationsProcessor.java

src/java/oracle/toplink/essentials/internal/databaseaccess/DatabasePlatform.java

src/java/oracle/toplink/essentials/internal/helper/DatabaseTable.java
src/java/oracle/toplink/essentials/tools/schemaframework/DefaultTableGenerator.java

src/java/oracle/toplink/essentials/tools/schemaframework/SchemaManager.java
src/java/oracle/toplink/essentials/tools/schemaframework/TableDefinition.java



Thanks
Pramod



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 foreign 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:
295c352,353
<         Vector foreignKeysClone = (Vector)getForeignKeys().clone();
---
>         DatabaseField dbField = null;
>         Vector foreignKeysClone = (Vector)getForeignKeys().clone();          
316a375,390
>         
>         Vector uniqueKeysClone = (Vector)getUniqueKeys().clone();       
>         setUniqueKeys(new Vector());
>         
>         Object[] uniqueKeysArray = uniqueKeysClone.toArray();
>         UniqueKeyConstraint uniqueKeyConstraint = new 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);            
>         }
> 
370a445,482
>     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;
>     }
> 
386a499,501
>         if (uniqueKeys != null) {
>             clone.setUniqueKeys((Vector)uniqueKeys.clone());
>         }        
394c509
<     public void createConstraints(AbstractSession session, Writer schemaWriter) throws TopLinkException {
---
>     public void createConstraints(AbstractSession session, Writer schemaWriter) throws TopLinkException {       
403c518,520
<                     schemaWriter.write(session.getPlatform().getStoredProcedureTerminationToken());
---
>                     if (createSQLFiles){                    
>                         schemaWriter.write(session.getPlatform().getStoredProcedureTerminationToken());
>                     }
408a526,540
>             
>             for (Enumeration uniqueKeysEnum = getUniqueKeys().elements();
>                      uniqueKeysEnum.hasMoreElements();) {              
>                 UniqueKeyConstraint uniqueKey = (UniqueKeyConstraint)uniqueKeysEnum.nextElement();
>                 buildUniqueConstraintCreationWriter(session, uniqueKey, schemaWriter).toString();
>                 try {
>                     if (createSQLFiles) {
>                         schemaWriter.write(session.getPlatform().getStoredProcedureTerminationToken());
>                     }
>                     schemaWriter.write("\n");
>                 } catch (IOException exception) {
>                     throw ValidationException.fileError(exception);
>                 }
>             }            
>             
425a558,568
>         
>         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()));
>         } 
>       
449c592,608
<                     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());
>                     }
475a635,642
>         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 */
>             }
>         }        
485a653,656
>     public Vector getUniqueKeys() {
>         return uniqueKeys;
>     }
>     
504a676,683
>     
>     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.21
diff -r1.21 EJBAnnotationsProcessor.java
1743,1746c1743
<             
<             for (String columnName : columnNames) {
<                 table.addUniqueConstraint(new DatabaseField(columnName));
<             }
---
>             table.addUniqueConstraint(columnNames);
1758c1755
< 
---
> 
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.7
diff -r1.7 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.20
diff -r1.20 EntityMappingsXMLProcessor.java
2489a2490
> /*        
2492a2494,2501
>  */
> /* Need to achieve this        
>         for (UniqueConstraint uniqueConstraint : (UniqueConstraint[]) constraints) {
>             // UniqueConstraint.columnNames()
>             String[] columnNames = uniqueConstraint.columnNames();
>             table.addUniqueConstraint(columnNames);
>         }        
>  */
2524c2533
< 
---
> 
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);