You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by jr...@apache.org on 2009/05/14 20:19:34 UTC

svn commit: r774860 - in /openjpa/trunk: openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/ openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/ openjpa-jdbc/src/main/java/org/apach...

Author: jrbauer
Date: Thu May 14 18:19:34 2009
New Revision: 774860

URL: http://svn.apache.org/viewvc?rev=774860&view=rev
Log:
OPENJPA-962 Committing code and tests contributed by Dianne Richards

Added:
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/EntityF.java   (with props)
    openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/TestManualDelimId.java   (with props)
Modified:
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/SequenceMapping.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaGenerator.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
    openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java
    openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java
    openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.java

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java?rev=774860&r1=774859&r2=774860&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/kernel/TableJDBCSeq.java Thu May 14 18:19:34 2009
@@ -366,8 +366,18 @@
      * Creates the object-level representation of the sequence table.
      */
     private void buildTable() {
-        String tableName = Strings.getClassName(_table);
-        String schemaName = Strings.getPackageName(_table);
+        String tableName = null;
+        String schemaName = "";
+        if (StringUtils.contains(_table,'.')) {
+            String[] tableParts = StringUtils.split(_table, '.');
+            // TODO: do we need to check for length? Could we have xxx. or .xxx?
+            schemaName = tableParts[0];
+            tableName = tableParts[1];
+        }
+        else {
+            tableName = _table;
+        }
+        
         if (schemaName.length() == 0)
             schemaName = Schemas.getNewTableSchema(_conf);
 

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/SequenceMapping.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/SequenceMapping.java?rev=774860&r1=774859&r2=774860&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/SequenceMapping.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/meta/SequenceMapping.java Thu May 14 18:19:34 2009
@@ -24,6 +24,7 @@
 import java.util.List;
 
 import org.apache.commons.lang.StringUtils;
+import org.apache.openjpa.conf.OpenJPAConfiguration;
 import org.apache.openjpa.jdbc.conf.JDBCSeqValue;
 import org.apache.openjpa.jdbc.kernel.ClassTableJDBCSeq;
 import org.apache.openjpa.jdbc.kernel.TableJDBCSeq;
@@ -159,10 +160,37 @@
 
     protected void addStandardProperties(StringBuffer props) {
         super.addStandardProperties(props);
-        appendProperty(props, PROP_TABLE, _table);
-        appendProperty(props, PROP_SEQUENCE_COL, _sequenceColumn);
-        appendProperty(props, PROP_PK_COL, _primaryKeyColumn);
-        appendProperty(props, PROP_PK_VALUE, _primaryKeyValue);
+        // Quotes are conditionally added to the following because the props
+        // are eventually passed to the Configurations.parseProperties()
+        // method, which strips off quotes. This is a problem when these
+        // properties are intentionally delimited with quotes. So, an extra
+        // set preserves the intended ones. While this is an ugly solution,
+        // it's less ugly than other ones.
+        String table = _table;
+        if (table != null && table.startsWith("\"")
+                && table.endsWith("\"")) {
+            table = "\"" + table + "\"";
+        }
+        String sequenceColumn = _sequenceColumn;
+        if (sequenceColumn != null && sequenceColumn.startsWith("\"")
+                && sequenceColumn.endsWith("\"")) {
+            sequenceColumn = "\"" + sequenceColumn + "\"";
+        }
+        String primaryKeyColumn = _primaryKeyColumn;
+        if (primaryKeyColumn !=null && primaryKeyColumn.startsWith("\"")
+                && primaryKeyColumn.endsWith("\"")) {
+            primaryKeyColumn = "\"" + primaryKeyColumn + "\"";
+        }
+        String primaryKeyValue = _primaryKeyValue;
+        if (primaryKeyValue != null && primaryKeyValue.startsWith("\"")
+                && primaryKeyValue.endsWith("\"")) {
+            primaryKeyValue = "\"" + primaryKeyValue + "\"";
+        }
+        
+        appendProperty(props, PROP_TABLE, table);
+        appendProperty(props, PROP_SEQUENCE_COL, sequenceColumn);
+        appendProperty(props, PROP_PK_COL, primaryKeyColumn);
+        appendProperty(props, PROP_PK_VALUE, primaryKeyValue);
         // Array of unique column names are passed to configuration
         // as a single string "x|y|z". The configurable (TableJDBCSeq) must
         // parse it back.

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaGenerator.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaGenerator.java?rev=774860&r1=774859&r2=774860&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaGenerator.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaGenerator.java Thu May 14 18:19:34 2009
@@ -488,9 +488,17 @@
         Table table;
         String tableSchema;
         for (int i = 0; cols != null && i < cols.length; i++) {
-            tableName = cols[i].getTableName();
-            tableSchema = StringUtils.trimToNull(cols[i].getSchemaName());
-
+            // TODO: Is this where we should handle this?
+            if (tableName == null || tableName.equals("%")) {
+                tableName = cols[i].getTableName();
+            }
+            if (schemaName == null) {
+                tableSchema = StringUtils.trimToNull(cols[i].getSchemaName());
+            }
+            else {
+                tableSchema = schemaName;
+            }
+            
             // ignore special tables
             if (!_openjpaTables &&
                 (tableName.toUpperCase().startsWith("OPENJPA_")

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java?rev=774860&r1=774859&r2=774860&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/SchemaTool.java Thu May 14 18:19:34 2009
@@ -470,6 +470,7 @@
         Table dbTable;
         Column[] cols;
         Column col;
+        String delim = _dict.getDelimiter();
         for (int i = 0; i < schemas.length; i++) {
             tabs = schemas[i].getTables();
             for (int j = 0; j < tabs.length; j++) {
@@ -477,14 +478,22 @@
                 dbTable = db.findTable(schemas[i], tabs[j].getFullName());
                 for (int k = 0; k < cols.length; k++) {
                     if (dbTable != null) {
-                        col = dbTable.getColumn(cols[k].getName());
+                        String colName = cols[k].getName();
+                        boolean delimCol = false;
+                        if (colName.startsWith(delim) 
+                                && colName.endsWith(delim)) {
+                            colName = colName.substring(1, colName.length()-1);
+                            delimCol = true;
+                        }
+                        col = dbTable.getColumn(colName);
                         if (col == null) {
                             if (addColumn(cols[k]))
                                 dbTable.importColumn(cols[k]);
                             else
                                 _log.warn(_loc.get("add-col", cols[k],
                                     tabs[j]));
-                        } else if (!cols[k].equalsColumn(col)) {
+                        // TODO: Find a way to compare these with delimCol
+                        } else if (!delimCol && !cols[k].equalsColumn(col)) {
                             _log.warn(_loc.get("bad-col", new Object[]{
                                 col, dbTable, col.getDescription(),
                                 cols[k].getDescription() }));

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?rev=774860&r1=774859&r2=774860&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java Thu May 14 18:19:34 2009
@@ -24,6 +24,7 @@
 import java.sql.SQLException;
 import java.sql.Types;
 import java.util.Arrays;
+import java.util.EnumSet;
 import java.util.Set;
 import java.util.StringTokenizer;
 
@@ -64,7 +65,7 @@
     public static final int db2ZOSV8xOrLater = 3;
     public static final int db2UDBV82OrLater = 4;
     public static final int db2ISeriesV5R4OrLater = 5;
-	protected static final String forUpdate = "FOR UPDATE";
+    protected static final String forUpdate = "FOR UPDATE";
     protected static final String withURClause = "WITH UR";
     protected static final String withCSClause = "WITH CS";
     protected static final String withRSClause = "WITH RS";
@@ -82,6 +83,9 @@
     protected int min = 0;
     
     private int defaultBatchLimit = 100;
+    
+    private EnumSet<DBIdentifiers> unsupportedDelimitedIds =
+        EnumSet.of(DBIdentifiers.COLUMN_COLUMN_DEFINITION); 
 
     public DB2Dictionary() {
         platform = "DB2";
@@ -244,9 +248,9 @@
     }
 
     public void connectedConfiguration(Connection conn) throws SQLException {
-    	super.connectedConfiguration(conn);
+        super.connectedConfiguration(conn);
 
-    	DatabaseMetaData metaData = conn.getMetaData();
+        DatabaseMetaData metaData = conn.getMetaData();
         String driverName = metaData.getDriverName();
         if (driverName != null && driverName.startsWith("IBM DB2"))
             driverVendor = VENDOR_IBM;
@@ -267,21 +271,21 @@
                 db2ServerType = db2ISeriesV5R4OrLater;
         }
         
-    	if (db2ServerType == 0) {
-    	    if (isJDBC3) {
-    	        maj = metaData.getDatabaseMajorVersion();
-    	        min = metaData.getDatabaseMinorVersion();
-    	    }
-    	    else
-    	        getProductVersionMajorMinor();
-
-    	    // Determine the type of DB2 database for ZOS & UDB
-    	    if (isDB2UDBV81OrEarlier())
-    	        db2ServerType = db2UDBV81OrEarlier;
-    	    else if (isDB2ZOSV8xOrLater())
-    	        db2ServerType = db2ZOSV8xOrLater;
-    	    else if (isDB2UDBV82OrLater())
-    	        db2ServerType = db2UDBV82OrLater;
+        if (db2ServerType == 0) {
+            if (isJDBC3) {
+                maj = metaData.getDatabaseMajorVersion();
+                min = metaData.getDatabaseMinorVersion();
+            }
+            else
+                getProductVersionMajorMinor();
+
+            // Determine the type of DB2 database for ZOS & UDB
+            if (isDB2UDBV81OrEarlier())
+                db2ServerType = db2UDBV81OrEarlier;
+            else if (isDB2ZOSV8xOrLater())
+                db2ServerType = db2ZOSV8xOrLater;
+            else if (isDB2UDBV82OrLater())
+                db2ServerType = db2UDBV82OrLater;
         }
 
         // verify that database product is supported
@@ -289,14 +293,14 @@
             throw new UnsupportedException(_loc.get("db-not-supported",
                 new Object[] {databaseProductName, databaseProductVersion }));
 
-    	if (maj >= 9 || (maj == 8 && min >= 2)) {
-    	    supportsLockingWithMultipleTables = true;
-    	    supportsLockingWithInnerJoin = true;
-    	    supportsLockingWithOuterJoin = true;
-    	    forUpdateClause = "WITH RR USE AND KEEP UPDATE LOCKS";
-    	    if (maj >=9)
-    	        supportsXMLColumn = true;
-    	}
+        if (maj >= 9 || (maj == 8 && min >= 2)) {
+            supportsLockingWithMultipleTables = true;
+            supportsLockingWithInnerJoin = true;
+            supportsLockingWithOuterJoin = true;
+            forUpdateClause = "WITH RR USE AND KEEP UPDATE LOCKS";
+            if (maj >=9)
+                supportsXMLColumn = true;
+        }
 
         // platform specific settings
         switch (db2ServerType) {
@@ -843,10 +847,10 @@
     }
     
     String nullSafe(String s) {
-    	return s == null ? "" : s;
+        return s == null ? "" : s;
     }
 
-	@Override
+    @Override
     protected Boolean matchErrorState(int subtype, Set<String> errorStates,
         SQLException ex) {
         Boolean recoverable = null;
@@ -864,4 +868,17 @@
         }
         return recoverable;
     }
+    
+    /**
+     * @return the unsupportedDelimitedIds
+     */
+    @Override
+    protected EnumSet<DBIdentifiers> getUnsupportedDelimitedIds() {
+        return unsupportedDelimitedIds;
+    }
+    
+    @Override
+    protected void setDelimitedCase(DatabaseMetaData metaData) {
+        delimitedCase = SCHEMA_CASE_PRESERVE;
+    }
 }

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java?rev=774860&r1=774859&r2=774860&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java Thu May 14 18:19:34 2009
@@ -53,6 +53,7 @@
 import java.util.Collection;
 import java.util.Collections;
 import java.util.Date;
+import java.util.EnumSet;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Iterator;
@@ -348,6 +349,36 @@
     protected final Set systemTableSet = new HashSet();
     protected final Set fixedSizeTypeNameSet = new HashSet();
     protected final Set typeModifierSet = new HashSet();
+    
+    private boolean delimitIds = false;
+    protected boolean supportsDelimitedIds = false;
+    protected String delimiter = "\"";
+    // Assume mixed case by default.
+    protected String delimitedCase = SCHEMA_CASE_PRESERVE;
+    
+    // TODO: complete the list
+    public static enum DBIdentifiers {
+        TABLE_NAME,
+        TABLE_SCHEMA,
+        TABLE_CATALOG,
+        SECONDARY_TABLE_NAME,
+        SECONDARY_TABLE_SCHEMA,
+        SECONDARY_TABLE_CATALOG,
+        TABLE_GEN_TABLE,
+        TABLE_GEN_SCHEMA,
+        TABLE_GEN_PK_COLUMN,
+        TABLE_GEN_VALUE_COLUMN,
+        COLUMN_NAME,
+        COLUMN_COLUMN_DEFINITION,
+        COLUMN_TABLE
+    }
+    
+    // TODO: describe; maybe make private
+    protected EnumSet<DBIdentifiers> unsupportedDelimitedIds =
+        EnumSet.noneOf(DBIdentifiers.class);
+    // TODO
+    // Should this be EnumSet.<DBIdentifiers>noneOf(....)
+    // or EnumSet<DBIdentifiers>.noneOf....?
 
     /**
      * If a native query begins with any of the values found here then it will
@@ -418,6 +449,10 @@
                         conn.getAutoCommit(), conn.getHoldability(),
                         conn.getTransactionIsolation()}));
             }
+            
+            // While we have the metaData, set some values from it
+            setSupportsDelimitedIds(metaData);
+            setDelimitedCase(metaData);
         }
         connected = true;
     }
@@ -2972,7 +3007,18 @@
             name = name.substring(1);
         String tableName = table.getName();
         int len = Math.min(tableName.length(), 7);
-        name = "I_" + shorten(tableName, len) + "_" + name;
+        String shortTableName = shorten(tableName, len);
+        String delim = getDelimiter();
+        if (shortTableName.startsWith(delim) 
+            && shortTableName.endsWith(delim)) {
+            name = delim + "I_" 
+                + shortTableName.substring(1, shortTableName.length() - 1) 
+                + "_" + name + delim;
+        }
+        else {
+            name = "I_" + shortTableName + "_" + name;
+        }
+        
         return makeNameValid(name, table.getSchema().getSchemaGroup(),
             maxIndexNameLength, NAME_ANY);
     }
@@ -3052,17 +3098,26 @@
      * '1', etc. 
      * Note that the given max len may be 0 if the database metadata is 
      * incomplete.
+     * 
+     * Note: If the name is delimited, make sure the ending delimiter is
+     * not stripped off.
      */
     protected String makeNameValid(String name, NameSet set, int maxLen,
         int nameType, boolean checkForUniqueness) {
+        boolean delimited = false;
+        String delimiter = getDelimiter();
+        if (name.startsWith(delimiter) && name.endsWith(delimiter)) {
+            delimited = true;
+        }
         if (maxLen < 1)
             maxLen = 255;
         if (name.length() > maxLen)
-            name = name.substring(0, maxLen);
+            name = removeEndingChars(name, name.length() - maxLen, 
+                delimited, delimiter);
         if (reservedWordSet.contains(name.toUpperCase())) {
             if (name.length() == maxLen)
-                name = name.substring(0, name.length() - 1);
-            name += "0";
+                name = removeEndingChars(name, 1, delimited, delimiter);
+            name = addCharsToEnd(name, "0", delimited, delimiter);
         }
 
         // now make sure the name is unique
@@ -3088,16 +3143,65 @@
                 // a single char for the version is probably enough, but might
                 // as well be general about it...
                 if (version > 1)
-                    name = name.substring(0, name.length() - chars);
+                    name = removeEndingChars(name, chars, delimited, delimiter);
                 if (version >= Math.pow(10, chars))
                     chars++;
                 if (name.length() + chars > maxLen)
-                    name = name.substring(0, maxLen - chars);
-                name = name + version;
+                    name = removeEndingChars(name, 
+                        name.length() + chars - maxLen, 
+                        delimited, delimiter);
+                name = addCharsToEnd(name, new Integer(version).toString(), 
+                    delimited, delimiter);
             }
         }
+        
+        if (delimited) {
+            String delimCase = getDelimitedCase();
+            if (delimCase.equals(SCHEMA_CASE_LOWER)) {
+                return name.toLowerCase();
+            }
+            else if (delimCase.equals(SCHEMA_CASE_UPPER)) {
+                return name.toUpperCase();
+            }
+            else {
+                return name;
+            }
+        }
+        // TODO: This is the original. Should the db supported case be checked?
         return name.toUpperCase();
     }
+    
+    private String removeEndingChars(String name, 
+        int charsToRemove,
+        boolean delimited, 
+        String delimiter) {
+        if (delimited) {
+            name = name.substring(0, name.length() - delimiter.length());
+            name = name.substring(0, name.length() - charsToRemove);
+            name = name + delimiter;
+        }
+        else {
+            name = name.substring(0, name.length() - charsToRemove);
+        }
+        
+        return name;
+    }
+    
+    private String addCharsToEnd(String name,
+        String charsToAdd,
+        boolean delimited,
+        String delimiter) {
+        if (delimited) {
+            name = name.substring(0, name.length() - delimiter.length());
+            name = name + charsToAdd;
+            name = name + delimiter;
+        }
+        else {
+            name = name + charsToAdd;
+        }
+        
+        return name;
+    }
 
     /**
      * Return a series of SQL statements to create the given table, complete
@@ -3997,6 +4101,25 @@
         if (objectName == null)
             return null;
 
+        // Handle delimited string differently. Return unquoted name.
+        if (delimitIds || 
+                objectName.startsWith(getDelimiter()) &&
+                objectName.endsWith(getDelimiter())) {
+            String delimCase = getDelimitedCase();
+            if (SCHEMA_CASE_UPPER.equals(delimCase)) {
+                objectName.toUpperCase();
+            }
+            else if (SCHEMA_CASE_LOWER.equals(delimCase)) {
+                objectName.toLowerCase();
+            }
+            
+            // TODO: maybe have a different method to remove quotes and
+            // call it from the calling methods
+            int delimLen = getDelimiter().length();
+            return objectName.substring(delimLen, 
+                objectName.length() - delimLen);
+        }
+        
         String scase = getSchemaCase();
         if (SCHEMA_CASE_LOWER.equals(scase))
             return objectName.toLowerCase();
@@ -4728,4 +4851,101 @@
                     length));
         return name;
     }
+    
+    public String delimitString(String name, DBIdentifiers type) {
+        if (StringUtils.isEmpty(name)) {
+            return null;
+        }
+        
+        if (!getSupportsDelimitedIds()) {
+            // TODO: log (or maybe log in the method itself; so maybe
+            // merge with next if stmt
+            return name;
+        }
+        
+        if (!delimitIds) {
+            return name;
+        }
+        // TODO: merge with if stmt above (maybe not, may want to log this)
+        if (!supportsDelimitedId(type)) {
+            // TODO: log
+            return name;
+        }
+        String delimitedString = delimiter + name + delimiter;
+        return delimitedString;
+    }
+
+    /**
+     * @return the unsupportedDelimitedIds
+     */
+    protected EnumSet<DBIdentifiers> getUnsupportedDelimitedIds() {
+        return unsupportedDelimitedIds;
+    }
+    
+    protected boolean supportsDelimitedId(DBIdentifiers type) {
+        if (getUnsupportedDelimitedIds().contains(type)) {
+            return false;
+        }
+        return true;
+    }
+
+    /**
+     * @return the delimiter
+     */
+    public String getDelimiter() {
+        return delimiter;
+    }
+    
+    protected String getDelimitedCase() {
+        return delimitedCase;
+    }
+
+    protected void setDelimitedCase(DatabaseMetaData metaData) {
+        try {
+            if (metaData.storesMixedCaseQuotedIdentifiers()) {
+                delimitedCase = SCHEMA_CASE_PRESERVE;
+            }
+            else if (metaData.storesUpperCaseQuotedIdentifiers()) {
+                delimitedCase = SCHEMA_CASE_UPPER;
+            }
+            else if (metaData.storesLowerCaseQuotedIdentifiers()) {
+                delimitedCase = SCHEMA_CASE_LOWER;
+            }
+        } catch (SQLException e) {
+            // TODO log this
+        }
+    }
+    
+    /**
+     * @return the supportsDelimitedIds
+     */
+    public boolean getSupportsDelimitedIds() {
+        return supportsDelimitedIds;
+    }
+
+    /**
+     * @param supportsDelimitedIds the supportsDelimitedIds to set
+     */
+    public void setSupportsDelimitedIds(DatabaseMetaData metaData) {
+        try {
+            supportsDelimitedIds = 
+                metaData.supportsMixedCaseQuotedIdentifiers();
+        } catch (SQLException e) {
+            // TODO log this, or should we throw an exception?
+        }
+    }
+
+    /**
+     * @return the delimitIds
+     */
+    public boolean isDelimitIds() {
+        return delimitIds;
+    }
+
+    /**
+     * @param delimitIds the delimitIds to set
+     */
+    public void setDelimitIds(boolean delimitIds) {
+        this.delimitIds = delimitIds;
+    }
 }
\ No newline at end of file

Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java?rev=774860&r1=774859&r2=774860&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java Thu May 14 18:19:34 2009
@@ -20,9 +20,8 @@
 
 import java.sql.DriverManager;
 import java.sql.SQLException;
-import java.util.ArrayList;
 import java.util.Arrays;
-import java.util.List;
+import java.util.EnumSet;
 import java.util.Set;
 
 import javax.sql.DataSource;
@@ -40,6 +39,9 @@
      * the DataSource.
      */
     public boolean shutdownOnClose = true;
+    
+    private EnumSet<DBIdentifiers> unsupportedDelimitedIds =
+        EnumSet.of(DBIdentifiers.COLUMN_COLUMN_DEFINITION); 
 
     public DerbyDictionary() {
         platform = "Apache Derby";
@@ -120,4 +122,13 @@
         }
         return recoverable;
     }
+
+    /**
+     * @return the unsupportedDelimitedIds
+     */
+    @Override
+    protected EnumSet<DBIdentifiers> getUnsupportedDelimitedIds() {
+        return unsupportedDelimitedIds;
+    }
+
 }

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java?rev=774860&r1=774859&r2=774860&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/AnnotationPersistenceMappingParser.java Thu May 14 18:19:34 2009
@@ -115,6 +115,8 @@
 
     private static final Map<Class, MappingTag> _tags =
         new HashMap<Class, MappingTag>();
+    
+    private DBDictionary _dict; 
 
     static {
         _tags.put(AssociationOverride.class, ASSOC_OVERRIDE);
@@ -199,6 +201,7 @@
 
     public AnnotationPersistenceMappingParser(JDBCConfiguration conf) {
         super(conf);
+        _dict = conf.getDBDictionaryInstance();
     }
 
     @Override
@@ -252,9 +255,17 @@
 
         meta = (SequenceMapping) getRepository().addSequenceMetaData(name);
         meta.setSequencePlugin(SequenceMapping.IMPL_VALUE_TABLE);
-        meta.setTable(toTableName(gen.schema(), gen.table()));
-        meta.setPrimaryKeyColumn(gen.pkColumnName());
-        meta.setSequenceColumn(gen.valueColumnName());
+        String schema = _dict.delimitString(gen.schema(), 
+            DBDictionary.DBIdentifiers.TABLE_GEN_SCHEMA);
+        String table = _dict.delimitString(gen.table(), 
+            DBDictionary.DBIdentifiers.TABLE_GEN_TABLE);
+        meta.setTable(toTableName(schema,table));
+        String pkColumnName = _dict.delimitString(gen.pkColumnName(), 
+            DBDictionary.DBIdentifiers.TABLE_GEN_PK_COLUMN);
+        meta.setPrimaryKeyColumn(pkColumnName);
+        String valueColumnName = _dict.delimitString(gen.valueColumnName(), 
+            DBDictionary.DBIdentifiers.TABLE_GEN_VALUE_COLUMN);
+        meta.setSequenceColumn(valueColumnName);
         meta.setPrimaryKeyValue(gen.pkColumnValue());
         meta.setInitialValue(gen.initialValue());
         meta.setAllocate(gen.allocationSize());
@@ -494,13 +505,18 @@
         Log log = getLog();
 
         String name;
+        String schema;
         List<Column> joins = null;
         for (SecondaryTable table : tables) {
-            name = table.name();
+            name = _dict.delimitString(table.name(),
+                DBDictionary.DBIdentifiers.SECONDARY_TABLE_NAME) ;
             if (StringUtils.isEmpty(name))
                 throw new MetaDataException(_loc.get("second-name", cm));
-            if (!StringUtils.isEmpty(table.schema()))
-                name = table.schema() + "." + name;
+            if (!StringUtils.isEmpty(table.schema())) {
+                schema = _dict.delimitString(table.schema(),
+                    DBDictionary.DBIdentifiers.SECONDARY_TABLE_SCHEMA);
+                name = schema + "." + name;
+            }
             if (table.pkJoinColumns().length > 0) {
                 joins = new ArrayList<Column>(table.pkJoinColumns().length);
                 for (PrimaryKeyJoinColumn join : table.pkJoinColumns())
@@ -517,42 +533,46 @@
      * Set class table.
      */
     private void parseTable(ClassMapping cm, Table table) {
-        String tableName = toTableName(table.schema(), table.name());
-        if (tableName != null)
-            cm.getMappingInfo().setTableName(tableName);
+        String tableName = _dict.delimitString(table.name(), 
+                        DBDictionary.DBIdentifiers.TABLE_NAME);
+        String schemaName = _dict.delimitString(table.schema(),
+            DBDictionary.DBIdentifiers.TABLE_SCHEMA);
+        String fullTableName = toTableName(schemaName, tableName);
+        if (fullTableName != null)
+            cm.getMappingInfo().setTableName(fullTableName);
 
-        addUniqueConstraints(tableName, cm, cm.getMappingInfo(), 
+        addUniqueConstraints(fullTableName, cm, cm.getMappingInfo(), 
         		table.uniqueConstraints());
     }
     
     Unique createUniqueConstraint(MetaDataContext ctx, UniqueConstraint anno) {
-		String[] columnNames = anno.columnNames();
-		if (columnNames == null || columnNames.length == 0)
+        String[] columnNames = anno.columnNames();
+        if (columnNames == null || columnNames.length == 0)
             throw new UserException(_loc.get("unique-no-column", ctx));
-		Unique uniqueConstraint = new Unique();
-		for (int i=0; i<columnNames.length; i++) {
-			if (StringUtils.isEmpty(columnNames[i]))
+        Unique uniqueConstraint = new Unique();
+        for (int i = 0; i < columnNames.length; i++) {
+            if (StringUtils.isEmpty(columnNames[i]))
                 throw new UserException(_loc.get("unique-empty-column",
                         Arrays.toString(columnNames), ctx));
-			Column column = new Column();
-			column.setName(columnNames[i]);
-			uniqueConstraint.addColumn(column);
-		}
-		return uniqueConstraint;
+            Column column = new Column();
+            column.setName(columnNames[i]);
+            uniqueConstraint.addColumn(column);
+        }
+        return uniqueConstraint;
     }
     
-    void addUniqueConstraints(String table, MetaDataContext ctx, 
-    		MappingInfo info, UniqueConstraint...uniqueConstraints) {
-    	for (UniqueConstraint anno : uniqueConstraints) {
-    		Unique unique = createUniqueConstraint(ctx, anno);
-    		unique.setTableName(table);
-    		if (info instanceof ClassMappingInfo)
-    			((ClassMappingInfo)info).addUnique(table, unique);
-    		else if (info instanceof FieldMappingInfo)
-    			((FieldMappingInfo)info).addJoinTableUnique(unique);
-    		else
-    			throw new InternalException();
-    	}
+    void addUniqueConstraints(String table, MetaDataContext ctx,
+        MappingInfo info, UniqueConstraint... uniqueConstraints) {
+        for (UniqueConstraint anno : uniqueConstraints) {
+            Unique unique = createUniqueConstraint(ctx, anno);
+            unique.setTableName(table);
+            if (info instanceof ClassMappingInfo)
+                ((ClassMappingInfo) info).addUnique(table, unique);
+            else if (info instanceof FieldMappingInfo)
+                ((FieldMappingInfo) info).addJoinTableUnique(unique);
+            else
+                throw new InternalException();
+        }
     }
 
     /**
@@ -735,16 +755,16 @@
     }
     
     void assertDefault(ForeignKey fk) {
-    	boolean isDefault = StringUtils.isEmpty(fk.name()) 
-    		&& fk.enabled() 
-    		&& !fk.deferred() 
-    		&& fk.deleteAction() == ForeignKeyAction.RESTRICT
-    		&& fk.updateAction() == ForeignKeyAction.RESTRICT
-    		&& fk.columnNames().length == 0
-    		&& fk.specified();
-    	if (!isDefault)
+        boolean isDefault = StringUtils.isEmpty(fk.name()) 
+            && fk.enabled() 
+            && !fk.deferred() 
+                && fk.deleteAction() == ForeignKeyAction.RESTRICT
+                && fk.updateAction() == ForeignKeyAction.RESTRICT
+            && fk.columnNames().length == 0
+            && fk.specified();
+        if (!isDefault)
             throw new UserException(_loc.get("implicit-non-default-fk", _cls,
-    				getSourceFile()).getMessage());
+                getSourceFile()).getMessage());
     }
     
 
@@ -1449,11 +1469,11 @@
         String secondary = null;
         for (int i = 0; i < pcols.length; i++) {
             if (cols.size() > i)
-                setupColumn((Column) cols.get(i), pcols[i]);
+                setupColumn((Column) cols.get(i), pcols[i], _dict);
             else {
                 if (cols.isEmpty())
                     cols = new ArrayList<Column>(pcols.length);
-                cols.add(newColumn(pcols[i]));
+                cols.add(newColumn(pcols[i], _dict));
             }
             
             if (xmlTypeClass != null
@@ -1469,7 +1489,9 @@
             }
 
             unique |= (pcols[i].unique()) ? TRUE : FALSE;
-            secondary = trackSecondaryTable(fm, secondary, pcols[i].table(), i);
+            String secTable = _dict.delimitString(pcols[i].table(),
+                DBDictionary.DBIdentifiers.SECONDARY_TABLE_NAME);
+        	secondary = trackSecondaryTable(fm, secondary,	secTable, i);
         }
 
         if (fm.isElementCollection())
@@ -1483,20 +1505,24 @@
     /**
      * Create a new schema column with information from the given annotation.
      */
-    private static Column newColumn(javax.persistence.Column anno) {
+    private static Column newColumn(javax.persistence.Column anno,
+        DBDictionary dict) {
         Column col = new Column();
-        setupColumn(col, anno);
+        setupColumn(col, anno, dict);
         return col;
     }
 
     /**
      * Setup the given column with information from the given annotation.
      */
-    private static void setupColumn(Column col, javax.persistence.Column anno) {
+    private static void setupColumn(Column col, javax.persistence.Column anno,
+        DBDictionary dict) {
         if (!StringUtils.isEmpty(anno.name()))
-            col.setName(anno.name());
+            col.setName(dict.delimitString(anno.name(),
+                DBDictionary.DBIdentifiers.COLUMN_NAME));
         if (!StringUtils.isEmpty(anno.columnDefinition()))
-            col.setTypeName(anno.columnDefinition());
+            col.setTypeName(dict.delimitString(anno.columnDefinition(),
+                DBDictionary.DBIdentifiers.COLUMN_COLUMN_DEFINITION));
         if (anno.precision() != 0)
             col.setSize(anno.precision());
         else if (anno.length() != 255)

Modified: openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.java?rev=774860&r1=774859&r2=774860&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/main/java/org/apache/openjpa/persistence/jdbc/PersistenceMappingDefaults.java Thu May 14 18:19:34 2009
@@ -89,9 +89,9 @@
 
         int nColumn = vers.getMappingInfo().getColumns().size();
         switch (nColumn) {
-	        case 0 : return NoneVersionStrategy.getInstance();
-	        case 1 : return new NumberVersionStrategy();
-	        default: return new MultiColumnVersionStrategy();
+            case 0 : return NoneVersionStrategy.getInstance();
+            case 1 : return new NumberVersionStrategy();
+            default: return new MultiColumnVersionStrategy();
         }
     }
 
@@ -135,7 +135,17 @@
         ClassMapping clm = fm.getDefiningMapping();
         Table table = getTable(clm);
         
-        String name = table.getName() + "_";
+        String name = table.getName();
+        String delim = dict.getDelimiter();
+        boolean isDelimited = false;
+        if (name.startsWith(delim) && name.endsWith(delim)) {
+            isDelimited = true;
+            name = name.substring(0,name.length()-1) + "_";
+        }
+        else {
+            name = name + "_";
+        }
+        
 
         // if this is an assocation table, spec says to suffix with table of
         // the related type. spec doesn't cover other cases; we're going to
@@ -147,6 +157,11 @@
             name += rel.getTable().getName();
         else
             name += fm.getName();
+        
+        if (isDelimited) {
+            name += "\"";
+        }
+        
         return name.replace('$', '_');
     }
     

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/EntityF.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/EntityF.java?rev=774860&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/EntityF.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/EntityF.java Thu May 14 18:19:34 2009
@@ -0,0 +1,199 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+package org.apache.openjpa.persistence.delimited.identifiers;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import javax.persistence.CollectionTable;
+import javax.persistence.Column;
+import javax.persistence.ElementCollection;
+import javax.persistence.Entity;
+import javax.persistence.Id;
+import javax.persistence.MapKeyColumn;
+import javax.persistence.SecondaryTable;
+import javax.persistence.Table;
+
+@Entity
+@Table(name="\"primary entityF\"", schema="\"delim id\"")
+@SecondaryTable(name="\"secondary entityF\"", schema="\"delim id\"")
+//@Table(name="primary_entityF", schema="delim_id")
+public class EntityF {
+    @Id
+    private int id;
+    @Column(name="\"f name\"")
+    private String name;
+    @Column(name="f_nonDelimName")
+    private String nonDelimName;
+    @Column(name="\"secondary name\"", table="\"secondary entityF\"")
+    private String secName;
+    
+    @ElementCollection
+    // CollectionTable with default name generation
+    @CollectionTable
+    private Set<String> collectionSet = new HashSet<String>();
+    
+    @ElementCollection
+    @CollectionTable(name="\"collectionDelimSet\"", schema="\"delim id\"")
+    private Set<String> collectionDelimSet = new HashSet<String>();
+    
+    @ElementCollection
+    @MapKeyColumn
+    private Map<String, String> collectionMap = new HashMap<String, String>();
+    
+    @ElementCollection
+    @MapKeyColumn(name="\"mapKey\"")
+    private Map<String, String> delimCollectionMap = new HashMap<String, String>();
+    
+    public EntityF(String name) {
+        this.name = name;
+    }
+    
+    public EntityF(int id, String name) {
+        this.id = id;
+        this.name = name;
+    }
+    
+    /**
+     * @return the id
+     */
+    public int getId() {
+        return id;
+    }
+    /**
+     * @param id the id to set
+     */
+    public void setId(int id) {
+        this.id = id;
+    }
+    /**
+     * @return the name
+     */
+    public String getName() {
+        return name;
+    }
+    /**
+     * @param name the name to set
+     */
+    public void setName(String name) {
+        this.name = name;
+    }
+
+    /**
+     * @return the nonDelimName
+     */
+    public String getNonDelimName() {
+        return nonDelimName;
+    }
+
+    /**
+     * @param nonDelimName the nonDelimName to set
+     */
+    public void setNonDelimName(String nonDelimName) {
+        this.nonDelimName = nonDelimName;
+    }
+
+    /**
+     * @return the secName
+     */
+    public String getSecName() {
+        return secName;
+    }
+
+    /**
+     * @param secName the secName to set
+     */
+    public void setSecName(String secName) {
+        this.secName = secName;
+    }
+
+    /**
+     * @return the collectionSet
+     */
+    public Set<String> getCollectionSet() {
+        return collectionSet;
+    }
+
+    /**
+     * @param collectionSet the collectionSet to set
+     */
+    public void setCollectionSet(Set<String> collectionSet) {
+        this.collectionSet = collectionSet;
+    }
+    
+    public void addCollectionSet(String item) {
+        collectionSet.add(item);
+    }
+
+    /**
+     * @return the collectionNamedSet
+     */
+    public Set<String> getCollectionDelimSet() {
+        return collectionDelimSet;
+    }
+
+    /**
+     * @param collectionNamedSet the collectionNamedSet to set
+     */
+    public void setCollectionDelimSet(Set<String> collectionDelimSet) {
+        this.collectionDelimSet = collectionDelimSet;
+    } 
+    
+    public void addCollectionDelimSet(String item) {
+        this.collectionDelimSet.add(item);
+    }
+
+    /**
+     * @return the collectionMap
+     */
+    public Map<String, String> getCollectionMap() {
+        return collectionMap;
+    }
+
+    /**
+     * @param collectionMap the collectionMap to set
+     */
+    public void setCollectionMap(Map<String, String> collectionMap) {
+        this.collectionMap = collectionMap;
+    }
+
+    public void addCollectionMap(String key, String value) {
+        collectionMap.put(key, value);
+    }
+
+    /**
+     * @return the delimCollectionMap
+     */
+    public Map<String, String> getDelimCollectionMap() {
+        return delimCollectionMap;
+    }
+
+    /**
+     * @param delimCollectionMap the delimCollectionMap to set
+     */
+    public void setDelimCollectionMap(Map<String, String> delimCollectionMap) {
+        this.delimCollectionMap = delimCollectionMap;
+    }
+    
+    public void addDelimCollectionMap(String key, String value) {
+        delimCollectionMap.put(key, value);
+    }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/EntityF.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/TestManualDelimId.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/TestManualDelimId.java?rev=774860&view=auto
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/TestManualDelimId.java (added)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/TestManualDelimId.java Thu May 14 18:19:34 2009
@@ -0,0 +1,115 @@
+package org.apache.openjpa.persistence.delimited.identifiers;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.sql.DBDictionary;
+import org.apache.openjpa.persistence.OpenJPAEntityManager;
+import org.apache.openjpa.persistence.test.SQLListenerTestCase;
+
+public class TestManualDelimId extends SQLListenerTestCase {
+    OpenJPAEntityManager em;
+    int id = 0;
+    EntityF entityF;
+    JDBCConfiguration conf;
+    DBDictionary dict;
+    
+    public void setUp() throws Exception {
+        // TODO: retest with DROP to figure out problem
+//        super.setUp(EntityF2.class,DROP_TABLES);
+        super.setUp(
+            org.apache.openjpa.persistence.delimited.identifiers.EntityF.class);
+        assertNotNull(emf);
+        
+        em = emf.createEntityManager();
+        assertNotNull(em);
+        
+        conf = (JDBCConfiguration) emf.getConfiguration();
+        dict = conf.getDBDictionaryInstance();
+    }
+
+    public void createEntityF(int id) {
+        entityF = new EntityF(id, "fName");
+        entityF.setNonDelimName("fNonDelimName");
+        entityF.setSecName("sec name");
+        entityF.addCollectionSet("xxx");
+        entityF.addCollectionSet("yyy");
+        entityF.addCollectionDelimSet("aaa");
+        entityF.addCollectionDelimSet("bbb");
+        entityF.addCollectionMap("aaa", "xxx");
+        entityF.addCollectionMap("bbb", "yyy");
+        entityF.addDelimCollectionMap("www", "xxx");
+        entityF.addDelimCollectionMap("yyy", "zzz");
+    }
+    
+    // TODO: temp - test on multiple DBs
+//    public void testDBCapability() {
+//        Connection conn = (Connection)em.getConnection();
+//        try {
+//            DatabaseMetaData meta = conn.getMetaData();
+//            System.out.println("LC - " + meta.storesLowerCaseIdentifiers());
+//            System.out.println("LCQ - " + meta.storesLowerCaseQuotedIdentifiers());
+//            System.out.println("MC - " + meta.storesMixedCaseIdentifiers());
+//            System.out.println("MCQ - " + meta.storesMixedCaseQuotedIdentifiers());
+//            System.out.println("UC - " + meta.storesUpperCaseIdentifiers());
+//            System.out.println("UCQ - " + meta.storesUpperCaseQuotedIdentifiers());
+//            System.out.println("");
+//            System.out.println("db product name - " + meta.getDatabaseProductName());
+//            System.out.println("db product version - " + meta.getDatabaseProductVersion());
+//            System.out.println("driver name - " + meta.getDriverName());
+//            System.out.println("driver version - " + meta.getDriverVersion());
+//        } catch (SQLException e) {
+//            e.printStackTrace();
+//        }
+//    }    
+    
+    public void testCreateF() {
+        id++;
+        createEntityF(id);
+        
+        em.getTransaction().begin();
+        em.persist(entityF);
+        em.getTransaction().commit();
+        
+        System.out.println(super.toString(sql));
+        
+//        getColumnInfo("\"primary_entityF\"", "\"f_name\"", "\"delim_id\"");
+//        getColumnInfo("\"primary entityF\"", null, "\"delim id\"");
+//        getColumnInfo("\"secondary entityF\"", null, "\"delim id\"");
+    }
+
+    // TODO: change to boolean return and remove assert
+//        private void getColumnInfo(String tableName, String columnName, String schemaName) {
+//            Connection conn = (Connection)em.getConnection();
+//            try {
+//                DatabaseMetaData meta = conn.getMetaData();
+//    //            tableName = "\"" + tableName + "\"";
+//                Column[] columns = dict.getColumns(meta, conn.getCatalog(), schemaName, tableName, columnName, conn);
+//                System.out.println("columns.length - " + columns.length); 
+//                
+////                assertEquals(1, columns.length);
+//                
+//                for (Column column : columns) {
+//                    System.out.println("column name - " + column.getName());
+//                    System.out.println("column fullName - " + column.getFullName());
+//                    System.out.println("column schemaName - " + column.getSchemaName());
+//                    System.out.println("column tableName - " + column.getTableName());
+//                    System.out.println("column description - " + column.getDescription());
+//                }
+//            } catch (SQLException e) {
+//                e.printStackTrace();
+//            }
+//            finally {
+//                try {
+//                    conn.commit();
+//                    conn.close();
+//                } catch (SQLException e) {
+//                    e.printStackTrace();
+//                    fail("problem closing connection");
+//                }
+//            }
+//        }
+}

Propchange: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/delimited/identifiers/TestManualDelimId.java
------------------------------------------------------------------------------
    svn:eol-style = native