You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by pc...@apache.org on 2006/07/19 23:35:07 UTC

svn commit: r423615 [31/44] - in /incubator/openjpa/trunk: ./ openjpa-jdbc-5/ openjpa-jdbc-5/src/ openjpa-jdbc-5/src/main/ openjpa-jdbc-5/src/main/java/ openjpa-jdbc-5/src/main/java/org/ openjpa-jdbc-5/src/main/java/org/apache/ openjpa-jdbc-5/src/main/...

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionaryFactory.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionaryFactory.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionaryFactory.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionaryFactory.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,592 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc.sql;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLException;
+import javax.sql.DataSource;
+
+import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
+import org.apache.openjpa.lib.conf.Configurations;
+import org.apache.openjpa.lib.log.Log;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.StoreException;
+import org.apache.openjpa.util.UserException;
+
+/**
+ * Factory class to instantiate a dictionary. It will use
+ * the following heuristic:
+ * <ul>
+ * <li>Check to see if there is a DictionaryClass property,
+ * and if so, use that to instantiate the dictionary.</li>
+ * <li>Check the URL in the JDBCConfiguration against a list
+ * of pre-defined URLs for various dictionaries.</li>
+ * <li>Check the driver in the JDBCConfiguration against a list of known
+ * patterns.</li>
+ * <li>Acquire a connection and check its database metadata.</li>
+ * <li>Return an instance of the generic DBDictionary.</li>
+ * </ul>
+ *
+ * @author Marc Prud'hommeaux
+ * @nojavadoc
+ */
+public class DBDictionaryFactory {
+
+    // pcl: can't use these classes directly because they rely on native libs
+    private static final String ORACLE_DICT_NAME =
+        "org.apache.openjpa.jdbc.sql.OracleDictionary";
+    private static final String HSQL_DICT_NAME =
+        "org.apache.openjpa.jdbc.sql.HSQLDictionary";
+
+    private static final Localizer _loc = Localizer.forPackage
+        (DBDictionaryFactory.class);
+
+    /**
+     * Create the dictionary for the given class name and properties.
+     */
+    public static DBDictionary newDBDictionary(JDBCConfiguration conf,
+        String dclass, String props) {
+        return newDBDictionary(conf, dclass, props, null);
+    }
+
+    /**
+     * Attempt to create the dictionary from the given connection URL and
+     * driver name, either or both of which may be null. If the dictionary
+     * cannot be calculated, returns null.
+     */
+    public static DBDictionary calculateDBDictionary(JDBCConfiguration conf,
+        String url, String driver, String props) {
+        String dclass = dictionaryClassForString(url);
+        if (dclass == null)
+            dclass = dictionaryClassForString(driver);
+        if (dclass == null)
+            return null;
+        return newDBDictionary(conf, dclass, props);
+    }
+
+    /**
+     * Create the dictionary using connection metadata to determine its type.
+     */
+    public static DBDictionary newDBDictionary(JDBCConfiguration conf,
+        DataSource ds, String props) {
+        Connection conn = null;
+        try {
+            conn = ds.getConnection();
+            DatabaseMetaData meta = conn.getMetaData();
+            String dclass = dictionaryClassForString(meta.getURL());
+            if (dclass == null)
+                dclass = dictionaryClassForString
+                    (meta.getDatabaseProductName());
+            if (dclass == null)
+                dclass = DBDictionary.class.getName();
+            return newDBDictionary(conf, dclass, props, conn);
+        } catch (SQLException se) {
+            throw new StoreException(se).setFatal(true);
+        } finally {
+            if (conn != null)
+                try {
+                    conn.close();
+                } catch (SQLException se) {
+                }
+        }
+    }
+
+    /**
+     * Create the dictionary using the given class name and properties; the
+     * connection may be null if not supplied to the factory.
+     */
+    private static DBDictionary newDBDictionary(JDBCConfiguration conf,
+        String dclass, String props, Connection conn) {
+        DBDictionary dict = null;
+        try {
+            dict = (DBDictionary) Class.forName(dclass, true,
+                DBDictionary.class.getClassLoader()).newInstance();
+        } catch (Exception e) {
+            throw new UserException(e).setFatal(true);
+        }
+
+        // warn if we could not locate the appropriate dictionary
+        Log log = conf.getLog(JDBCConfiguration.LOG_JDBC);
+        if (log.isWarnEnabled() && dict.getClass() == DBDictionary.class)
+            log.warn(_loc.get("warn-generic"));
+
+        if (log.isInfoEnabled()) {
+            String infoString = "";
+            if (conn != null) {
+                try {
+                    DatabaseMetaData meta = conn.getMetaData();
+                    infoString = " (" + meta.getDatabaseProductName() + " "
+                        + meta.getDatabaseProductVersion() + " ,"
+                        + meta.getDriverName() + " "
+                        + meta.getDriverVersion() + ")";
+                } catch (SQLException se) {
+                    if (log.isTraceEnabled())
+                        log.trace(se.toString(), se);
+                }
+            }
+
+            log.info(_loc.get("using-dict", dclass, infoString));
+        }
+
+        // set the dictionary's metadata
+        Configurations.configureInstance(dict, conf, props, "DBDictionary");
+        if (conn != null) {
+            try {
+                dict.connectedConfiguration(conn);
+            } catch (SQLException se) {
+                throw new StoreException(se).setFatal(true);
+            }
+        }
+        return dict;
+    }
+
+    /**
+     * Guess the dictionary class name to use based on the product string.
+     */
+    private static String dictionaryClassForString(String prod) {
+        if (prod == null || prod.length() == 0)
+            return null;
+        prod = prod.toLowerCase();
+
+        if (prod.indexOf("oracle") != -1)
+            return ORACLE_DICT_NAME;
+        if (prod.indexOf("sqlserver") != -1)
+            return SQLServerDictionary.class.getName();
+        if (prod.indexOf("jsqlconnect") != -1)
+            return SQLServerDictionary.class.getName();
+        if (prod.indexOf("mysql") != -1)
+            return MySQLDictionary.class.getName();
+        if (prod.indexOf("postgres") != -1)
+            return PostgresDictionary.class.getName();
+        if (prod.indexOf("sybase") != -1)
+            return SybaseDictionary.class.getName();
+        if (prod.indexOf("adaptive server") != -1)
+            return SybaseDictionary.class.getName();
+        if (prod.indexOf("informix") != -1)
+            return InformixDictionary.class.getName();
+        if (prod.indexOf("hsql") != -1)
+            return HSQL_DICT_NAME;
+        if (prod.indexOf("foxpro") != -1)
+            return FoxProDictionary.class.getName();
+        if (prod.indexOf("interbase") != -1)
+            return InterbaseDictionary.class.getName();
+        if (prod.indexOf("jdatastore") != -1)
+            return JDataStoreDictionary.class.getName();
+        if (prod.indexOf("borland") != -1)
+            return JDataStoreDictionary.class.getName();
+        if (prod.indexOf("access") != -1)
+            return AccessDictionary.class.getName();
+        if (prod.indexOf("pointbase") != -1)
+            return PointbaseDictionary.class.getName();
+        if (prod.indexOf("empress") != -1)
+            return EmpressDictionary.class.getName();
+        if (prod.indexOf("firebird") != -1)
+            return FirebirdDictionary.class.getName();
+        if (prod.indexOf("cache") != -1)
+            return CacheDictionary.class.getName();
+        if (prod.indexOf("derby") != -1)
+            return DerbyDictionary.class.getName();
+        // test db2 last, because there's a decent chance this string could
+        // appear in the URL of another database (like if the db is named
+        // "testdb2" or something)
+        if (prod.indexOf("db2") != -1 || prod.indexOf("as400") != -1)
+            return DB2Dictionary.class.getName();
+
+        // known dbs that we don't support
+        if (prod.indexOf("cloudscape") != -1)
+            return DBDictionary.class.getName();
+        if (prod.indexOf("daffodil") != -1)
+            return DBDictionary.class.getName();
+        if (prod.indexOf("sapdb") != -1)
+            return DBDictionary.class.getName();
+        if (prod.indexOf("idb") != -1) // instantdb
+            return DBDictionary.class.getName();
+
+        // give up
+        return null;
+    }
+
+    /**
+     * Return a string containing all the property values of the given
+     * database metadata.
+     */
+    public static String toString(DatabaseMetaData meta)
+        throws SQLException {
+        String lineSep = System.getProperty("line.separator");
+        StringBuffer buf = new StringBuffer();
+        try {
+            buf.append("catalogSeparator: ")
+                .append(meta.getCatalogSeparator())
+                .append(lineSep)
+                .append("catalogTerm: ")
+                .append(meta.getCatalogTerm())
+                .append(lineSep)
+                .append("databaseProductName: ")
+                .append(meta.getDatabaseProductName())
+                .append(lineSep)
+                .append("databaseProductVersion: ")
+                .append(meta.getDatabaseProductVersion())
+                .append(lineSep)
+                .append("driverName: ")
+                .append(meta.getDriverName())
+                .append(lineSep)
+                .append("driverVersion: ")
+                .append(meta.getDriverVersion())
+                .append(lineSep)
+                .append("extraNameCharacters: ")
+                .append(meta.getExtraNameCharacters())
+                .append(lineSep)
+                .append("identifierQuoteString: ")
+                .append(meta.getIdentifierQuoteString())
+                .append(lineSep)
+                .append("numericFunctions: ")
+                .append(meta.getNumericFunctions())
+                .append(lineSep)
+                .append("procedureTerm: ")
+                .append(meta.getProcedureTerm())
+                .append(lineSep)
+                .append("schemaTerm: ")
+                .append(meta.getSchemaTerm())
+                .append(lineSep)
+                .append("searchStringEscape: ")
+                .append(meta.getSearchStringEscape())
+                .append(lineSep)
+                .append("sqlKeywords: ")
+                .append(meta.getSQLKeywords())
+                .append(lineSep)
+                .append("stringFunctions: ")
+                .append(meta.getStringFunctions())
+                .append(lineSep)
+                .append("systemFunctions: ")
+                .append(meta.getSystemFunctions())
+                .append(lineSep)
+                .append("timeDateFunctions: ")
+                .append(meta.getTimeDateFunctions())
+                .append(lineSep)
+                .append("url: ")
+                .append(meta.getURL())
+                .append(lineSep)
+                .append("userName: ")
+                .append(meta.getUserName())
+                .append(lineSep)
+                .append("defaultTransactionIsolation: ")
+                .append(meta.getDefaultTransactionIsolation())
+                .append(lineSep)
+                .append("driverMajorVersion: ")
+                .append(meta.getDriverMajorVersion())
+                .append(lineSep)
+                .append("driverMinorVersion: ")
+                .append(meta.getDriverMinorVersion())
+                .append(lineSep)
+                .append("maxBinaryLiteralLength: ")
+                .append(meta.getMaxBinaryLiteralLength())
+                .append(lineSep)
+                .append("maxCatalogNameLength: ")
+                .append(meta.getMaxCatalogNameLength())
+                .append(lineSep)
+                .append("maxCharLiteralLength: ")
+                .append(meta.getMaxCharLiteralLength())
+                .append(lineSep)
+                .append("maxColumnNameLength: ")
+                .append(meta.getMaxColumnNameLength())
+                .append(lineSep)
+                .append("maxColumnsInGroupBy: ")
+                .append(meta.getMaxColumnsInGroupBy())
+                .append(lineSep)
+                .append("maxColumnsInIndex: ")
+                .append(meta.getMaxColumnsInIndex())
+                .append(lineSep)
+                .append("maxColumnsInOrderBy: ")
+                .append(meta.getMaxColumnsInOrderBy())
+                .append(lineSep)
+                .append("maxColumnsInSelect: ")
+                .append(meta.getMaxColumnsInSelect())
+                .append(lineSep)
+                .append("maxColumnsInTable: ")
+                .append(meta.getMaxColumnsInTable())
+                .append(lineSep)
+                .append("maxConnections: ")
+                .append(meta.getMaxConnections())
+                .append(lineSep)
+                .append("maxCursorNameLength: ")
+                .append(meta.getMaxCursorNameLength())
+                .append(lineSep)
+                .append("maxIndexLength: ")
+                .append(meta.getMaxIndexLength())
+                .append(lineSep)
+                .append("maxProcedureNameLength: ")
+                .append(meta.getMaxProcedureNameLength())
+                .append(lineSep)
+                .append("maxRowSize: ")
+                .append(meta.getMaxRowSize())
+                .append(lineSep)
+                .append("maxSchemaNameLength: ")
+                .append(meta.getMaxSchemaNameLength())
+                .append(lineSep)
+                .append("maxStatementLength: ")
+                .append(meta.getMaxStatementLength())
+                .append(lineSep)
+                .append("maxStatements: ")
+                .append(meta.getMaxStatements())
+                .append(lineSep)
+                .append("maxTableNameLength: ")
+                .append(meta.getMaxTableNameLength())
+                .append(lineSep)
+                .append("maxTablesInSelect: ")
+                .append(meta.getMaxTablesInSelect())
+                .append(lineSep)
+                .append("maxUserNameLength: ")
+                .append(meta.getMaxUserNameLength())
+                .append(lineSep)
+                .append("isCatalogAtStart: ")
+                .append(meta.isCatalogAtStart())
+                .append(lineSep)
+                .append("isReadOnly: ")
+                .append(meta.isReadOnly())
+                .append(lineSep)
+                .append("nullPlusNonNullIsNull: ")
+                .append(meta.nullPlusNonNullIsNull())
+                .append(lineSep)
+                .append("nullsAreSortedAtEnd: ")
+                .append(meta.nullsAreSortedAtEnd())
+                .append(lineSep)
+                .append("nullsAreSortedAtStart: ")
+                .append(meta.nullsAreSortedAtStart())
+                .append(lineSep)
+                .append("nullsAreSortedHigh: ")
+                .append(meta.nullsAreSortedHigh())
+                .append(lineSep)
+                .append("nullsAreSortedLow: ")
+                .append(meta.nullsAreSortedLow())
+                .append(lineSep)
+                .append("storesLowerCaseIdentifiers: ")
+                .append(meta.storesLowerCaseIdentifiers())
+                .append(lineSep)
+                .append("storesLowerCaseQuotedIdentifiers: ")
+                .append(meta.storesLowerCaseQuotedIdentifiers())
+                .append(lineSep)
+                .append("storesMixedCaseIdentifiers: ")
+                .append(meta.storesMixedCaseIdentifiers())
+                .append(lineSep)
+                .append("storesMixedCaseQuotedIdentifiers: ")
+                .append(meta.storesMixedCaseQuotedIdentifiers())
+                .append(lineSep)
+                .append("storesUpperCaseIdentifiers: ")
+                .append(meta.storesUpperCaseIdentifiers())
+                .append(lineSep)
+                .append("storesUpperCaseQuotedIdentifiers: ")
+                .append(meta.storesUpperCaseQuotedIdentifiers())
+                .append(lineSep)
+                .append("supportsAlterTableWithAddColumn: ")
+                .append(meta.supportsAlterTableWithAddColumn())
+                .append(lineSep)
+                .append("supportsAlterTableWithDropColumn: ")
+                .append(meta.supportsAlterTableWithDropColumn())
+                .append(lineSep)
+                .append("supportsANSI92EntryLevelSQL: ")
+                .append(meta.supportsANSI92EntryLevelSQL())
+                .append(lineSep)
+                .append("supportsANSI92FullSQL: ")
+                .append(meta.supportsANSI92FullSQL())
+                .append(lineSep)
+                .append("supportsANSI92IntermediateSQL: ")
+                .append(meta.supportsANSI92IntermediateSQL())
+                .append(lineSep)
+                .append("supportsCatalogsInDataManipulation: ")
+                .append(meta.supportsCatalogsInDataManipulation())
+                .append(lineSep)
+                .append("supportsCatalogsInIndexDefinitions: ")
+                .append(meta.supportsCatalogsInIndexDefinitions())
+                .append(lineSep)
+                .append("supportsCatalogsInPrivilegeDefinitions: ")
+                .append(meta.supportsCatalogsInPrivilegeDefinitions())
+                .append(lineSep)
+                .append("supportsCatalogsInProcedureCalls: ")
+                .append(meta.supportsCatalogsInProcedureCalls())
+                .append(lineSep)
+                .append("supportsCatalogsInTableDefinitions: ")
+                .append(meta.supportsCatalogsInTableDefinitions())
+                .append(lineSep)
+                .append("supportsColumnAliasing: ")
+                .append(meta.supportsColumnAliasing())
+                .append(lineSep)
+                .append("supportsConvert: ")
+                .append(meta.supportsConvert())
+                .append(lineSep)
+                .append("supportsCoreSQLGrammar: ")
+                .append(meta.supportsCoreSQLGrammar())
+                .append(lineSep)
+                .append("supportsCorrelatedSubqueries: ")
+                .append(meta.supportsCorrelatedSubqueries())
+                .append(lineSep)
+                .append(
+                    "supportsDataDefinitionAndDataManipulationTransactions: ")
+                .append(meta.
+                    supportsDataDefinitionAndDataManipulationTransactions())
+                .append(lineSep)
+                .append("supportsDataManipulationTransactionsOnly: ")
+                .append(meta.supportsDataManipulationTransactionsOnly())
+                .append(lineSep)
+                .append("supportsDifferentTableCorrelationNames: ")
+                .append(meta.supportsDifferentTableCorrelationNames())
+                .append(lineSep)
+                .append("supportsExpressionsInOrderBy: ")
+                .append(meta.supportsExpressionsInOrderBy())
+                .append(lineSep)
+                .append("supportsExtendedSQLGrammar: ")
+                .append(meta.supportsExtendedSQLGrammar())
+                .append(lineSep)
+                .append("supportsFullOuterJoins: ")
+                .append(meta.supportsFullOuterJoins())
+                .append(lineSep)
+                .append("supportsGroupBy: ")
+                .append(meta.supportsGroupBy())
+                .append(lineSep)
+                .append("supportsGroupByBeyondSelect: ")
+                .append(meta.supportsGroupByBeyondSelect())
+                .append(lineSep)
+                .append("supportsGroupByUnrelated: ")
+                .append(meta.supportsGroupByUnrelated())
+                .append(lineSep)
+                .append("supportsIntegrityEnhancementFacility: ")
+                .append(meta.supportsIntegrityEnhancementFacility())
+                .append(lineSep)
+                .append("supportsLikeEscapeClause: ")
+                .append(meta.supportsLikeEscapeClause())
+                .append(lineSep)
+                .append("supportsLimitedOuterJoins: ")
+                .append(meta.supportsLimitedOuterJoins())
+                .append(lineSep)
+                .append("supportsMinimumSQLGrammar: ")
+                .append(meta.supportsMinimumSQLGrammar())
+                .append(lineSep)
+                .append("supportsMixedCaseIdentifiers: ")
+                .append(meta.supportsMixedCaseIdentifiers())
+                .append(lineSep)
+                .append("supportsMixedCaseQuotedIdentifiers: ")
+                .append(meta.supportsMixedCaseQuotedIdentifiers())
+                .append(lineSep)
+                .append("supportsMultipleResultSets: ")
+                .append(meta.supportsMultipleResultSets())
+                .append(lineSep)
+                .append("supportsMultipleTransactions: ")
+                .append(meta.supportsMultipleTransactions())
+                .append(lineSep)
+                .append("supportsNonNullableColumns: ")
+                .append(meta.supportsNonNullableColumns())
+                .append(lineSep)
+                .append("supportsOpenCursorsAcrossCommit: ")
+                .append(meta.supportsOpenCursorsAcrossCommit())
+                .append(lineSep)
+                .append("supportsOpenCursorsAcrossRollback: ")
+                .append(meta.supportsOpenCursorsAcrossRollback())
+                .append(lineSep)
+                .append("supportsOpenStatementsAcrossCommit: ")
+                .append(meta.supportsOpenStatementsAcrossCommit())
+                .append(lineSep)
+                .append("supportsOpenStatementsAcrossRollback: ")
+                .append(meta.supportsOpenStatementsAcrossRollback())
+                .append(lineSep)
+                .append("supportsOrderByUnrelated: ")
+                .append(meta.supportsOrderByUnrelated())
+                .append(lineSep)
+                .append("supportsOuterJoins: ")
+                .append(meta.supportsOuterJoins())
+                .append(lineSep)
+                .append("supportsPositionedDelete: ")
+                .append(meta.supportsPositionedDelete())
+                .append(lineSep)
+                .append("supportsPositionedUpdate: ")
+                .append(meta.supportsPositionedUpdate())
+                .append(lineSep)
+                .append("supportsSchemasInDataManipulation: ")
+                .append(meta.supportsSchemasInDataManipulation())
+                .append(lineSep)
+                .append("supportsSchemasInIndexDefinitions: ")
+                .append(meta.supportsSchemasInIndexDefinitions())
+                .append(lineSep)
+                .append("supportsSchemasInPrivilegeDefinitions: ")
+                .append(meta.supportsSchemasInPrivilegeDefinitions())
+                .append(lineSep)
+                .append("supportsSchemasInProcedureCalls: ")
+                .append(meta.supportsSchemasInProcedureCalls())
+                .append(lineSep)
+                .append("supportsSchemasInTableDefinitions: ")
+                .append(meta.supportsSchemasInTableDefinitions())
+                .append(lineSep)
+                .append("supportsSelectForUpdate: ")
+                .append(meta.supportsSelectForUpdate())
+                .append(lineSep)
+                .append("supportsStoredProcedures: ")
+                .append(meta.supportsStoredProcedures())
+                .append(lineSep)
+                .append("supportsSubqueriesInComparisons: ")
+                .append(meta.supportsSubqueriesInComparisons())
+                .append(lineSep)
+                .append("supportsSubqueriesInExists: ")
+                .append(meta.supportsSubqueriesInExists())
+                .append(lineSep)
+                .append("supportsSubqueriesInIns: ")
+                .append(meta.supportsSubqueriesInIns())
+                .append(lineSep)
+                .append("supportsSubqueriesInQuantifieds: ")
+                .append(meta.supportsSubqueriesInQuantifieds())
+                .append(lineSep)
+                .append("supportsTableCorrelationNames: ")
+                .append(meta.supportsTableCorrelationNames())
+                .append(lineSep)
+                .append("supportsTransactions: ")
+                .append(meta.supportsTransactions())
+                .append(lineSep)
+                .append("supportsUnion: ")
+                .append(meta.supportsUnion())
+                .append(lineSep)
+                .append("supportsUnionAll: ")
+                .append(meta.supportsUnionAll())
+                .append(lineSep)
+                .append("usesLocalFilePerTable: ")
+                .append(meta.usesLocalFilePerTable())
+                .append(lineSep)
+                .append("usesLocalFiles: ")
+                .append(meta.usesLocalFiles())
+                .append(lineSep)
+                .append("allProceduresAreCallable: ")
+                .append(meta.allProceduresAreCallable())
+                .append(lineSep)
+                .append("allTablesAreSelectable: ")
+                .append(meta.allTablesAreSelectable())
+                .append(lineSep)
+                .append("dataDefinitionCausesTransactionCommit: ")
+                .append(meta.dataDefinitionCausesTransactionCommit())
+                .append(lineSep)
+                .append("dataDefinitionIgnoredInTransactions: ")
+                .append(meta.dataDefinitionIgnoredInTransactions())
+                .append(lineSep)
+                .append("doesMaxRowSizeIncludeBlobs: ")
+                .append(meta.doesMaxRowSizeIncludeBlobs())
+                .append(lineSep)
+                .append("supportsBatchUpdates: ")
+                .append(meta.supportsBatchUpdates());
+        } catch (Throwable t) {
+            // maybe abstract method error for jdbc 3 metadata method, or
+            // other error
+            buf.append(lineSep).append("Caught throwable: ").append(t);
+        }
+
+        return buf.toString();
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionaryFactory.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,93 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc.sql;
+
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Arrays;
+import javax.sql.DataSource;
+
+/**
+ * Dictionary for Apache Derby (formerly Cloudscape).
+ */
+public class DerbyDictionary
+    extends AbstractDB2Dictionary {
+
+    /**
+     * If true, we will shutdown the embedded database when closing
+     * the DataSource.
+     */
+    public boolean shutdownOnClose = true;
+
+    public DerbyDictionary() {
+        platform = "Apache Derby";
+        validationSQL = "VALUES(1)";
+        stringLengthFunction = "LENGTH({0})";
+        substringFunctionName = "SUBSTR";
+
+        maxConstraintNameLength = 18;
+        maxIndexNameLength = 18;
+        maxColumnNameLength = 30;
+        maxTableNameLength = 18;
+
+        useGetBytesForBlobs = true;
+        useSetBytesForBlobs = true;
+
+        allowsAliasInBulkClause = false;
+        supportsDeferredConstraints = false;
+        supportsSelectForUpdate = true;
+        supportsDefaultDeleteAction = false;
+        requiresCastForMathFunctions = true;
+        requiresCastForComparisons = true;
+
+        fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
+            "BIGINT", "INTEGER",
+        }));
+        reservedWordSet.addAll(Arrays.asList(new String[]{
+            "ALIAS", "BIGINT", "BOOLEAN", "CALL", "CLASS",
+            "COPY", "DB2J_DEBUG", "EXECUTE", "EXPLAIN",
+            "FILE", "FILTER", "GETCURRENTCONNECTION", "INDEX",
+            "INSTANCEOF", "METHOD", "NEW", "OFF", "OUT", "PROPERTIES",
+            "PUBLICATION", "RECOMPILE", "REFRESH", "RENAME",
+            "RUNTIMESTATISTICS", "STATEMENT", "STATISTICS",
+            "TIMING", "WAIT", "XML",
+        }));
+    }
+
+    public void closeDataSource(DataSource dataSource) {
+        super.closeDataSource(dataSource);
+
+        if (!shutdownOnClose)
+            return;
+
+        // as well as closing the DataSource, we also need to
+        // shut down the instance if we are using an embedded database, which
+        // can only be done by connecting to the same URL with the
+        // ";shutdown=true" string appended to the end
+        // see: http://db.apache.org/derby/docs/dev/devguide/tdevdvlp40464.html
+        if (conf != null && conf.getConnectionDriverName() != null &&
+            conf.getConnectionDriverName().indexOf("EmbeddedDriver") != -1) {
+            try {
+                DriverManager.getConnection(conf.getConnectionURL()
+                    + ";shutdown=true");
+            } catch (SQLException e) {
+                // we actuall expect a SQLException to be thrown here:
+                // Derby strangely uses that as a mechanism to report
+                // a successful shutdown
+            }
+        }
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DerbyDictionary.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/EmpressDictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/EmpressDictionary.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/EmpressDictionary.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/EmpressDictionary.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc.sql;
+
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.util.Arrays;
+
+import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Table;
+
+/**
+ * Dictionary for Empress using ODBC server combined with their
+ * type 2 driver. This dictionary may issues with other
+ * driver/topology configurations.
+ *  Empress does not allow multiple connections to read rows
+ * read in a transaction, effectively forcing pessimistic transactions
+ * regardless of the Optimistic setting. To allow users to use
+ * optimistic transactions in a multi-connection evironment, you
+ * must set the AllowConcurrentRead setting to true in addition
+ * to standard options.
+ *  Empress has the following additional limitations:
+ * <ul>
+ * <li>Foreign keys are quite limited in Empress and it is recommended
+ * that these be created by hand.</li>
+ * <li>Batching can be unreliable. Using BatchLimit=0 is strongly
+ * recommended.</li>
+ * <li>Using AllowConcurrentRead should be accompanied by
+ * SimulateLocking=true</li>
+ * <li>Connections should be rolled back on return to ensure locks
+ * are released (see OpenJPA default DataSource documentation.</li>
+ * <li>Certain outer joins requiring parameters in a subselect is not
+ * supported by Empress and may under certain configurations cause
+ * size () calls on query results and LRS fields to throw an exception.</li>
+ * <li>Certain aggregate functions are not supported.</li>
+ * </ul>
+ */
+public class EmpressDictionary
+    extends DBDictionary {
+
+    /**
+     * This setting inserts "BYPASS" after every "SELECT". This
+     * allows for multiple transactional reads of the same row
+     * from different connections at the expense of loss of
+     * pessimistic locking. Defaults to false.
+     */
+    public boolean allowConcurrentRead = false;
+
+    public EmpressDictionary() {
+        platform = "Empress";
+
+        validationSQL = "SELECT DISTINCT today FROM sys_tables";
+        joinSyntax = SYNTAX_TRADITIONAL;
+        toUpperCaseFunction = "TOUPPER({0})";
+        toLowerCaseFunction = "TOLOWER({0})";
+
+        supportsDeferredConstraints = false;
+        requiresAliasForSubselect = true;
+        maxTableNameLength = 28;
+        maxColumnNameLength = 28;
+        maxIndexNameLength = 28;
+        maxConstraintNameLength = 28;
+        schemaCase = SCHEMA_CASE_PRESERVE;
+
+        useGetBytesForBlobs = true;
+        useSetBytesForBlobs = true;
+        useGetStringForClobs = true;
+        useSetStringForClobs = true;
+
+        clobTypeName = "TEXT";
+        blobTypeName = "BULK";
+        realTypeName = "FLOAT(8)";
+        bigintTypeName = "DECIMAL(38)";
+        timestampTypeName = "DATE";
+        varcharTypeName = "CHARACTER";
+        tinyintTypeName = "DOUBLE PRECISION";
+        doubleTypeName = "SMALLINT";
+        bitTypeName = "SMALLINT";
+
+        fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
+            "TEXT", "BULK", "LONGFLOAT", "INTEGER64", "SHORTINTEGER",
+            "LONGINTEGER",
+        }));
+    }
+
+    public boolean isSystemIndex(String name, Table table) {
+        return name.toUpperCase().startsWith("SYS_");
+    }
+
+    public SQLBuffer toSelect(SQLBuffer selects, JDBCFetchConfiguration fetch,
+        SQLBuffer from, SQLBuffer where, SQLBuffer group,
+        SQLBuffer having, SQLBuffer order,
+        boolean distinct, boolean forUpdate, long startIdx, long endIdx) {
+        if (!allowConcurrentRead)
+            return super.toSelect(selects, fetch, from, where, group,
+                having, order, distinct, forUpdate, startIdx, endIdx);
+
+        // override to allow a "BYPASS" to be inserted post-"select"
+        // depending on allowConcurrentRead setting
+        SQLBuffer buf = new SQLBuffer(this);
+        buf.append("SELECT BYPASS ");
+        if (distinct)
+            buf.append("DISTINCT ");
+        buf.append(selects).append(" FROM ").append(from);
+
+        if (where != null && !where.isEmpty())
+            buf.append(" WHERE ").append(where);
+        if (group != null && !group.isEmpty())
+            buf.append(" GROUP BY ").append(group);
+        if (having != null && !having.isEmpty())
+            buf.append(" HAVING ").append(having);
+        if (order != null && !order.isEmpty())
+            buf.append(" ORDER BY ").append(order);
+        return buf;
+    }
+
+    public String[] getDropColumnSQL(Column column) {
+        // empress wants dropped columns in the form: ALTER TABLE foo
+        // DELETE columnToDrop
+        return new String[]{ "ALTER TABLE "
+            + getFullName(column.getTable(), false) + " DELETE " + column };
+    }
+
+    public void setFloat(PreparedStatement stmnt, int idx, float val,
+        Column col)
+        throws SQLException {
+        // empress seems to allow INFINITY to be stored, but not retrieved,
+        // which can prove to be difficult to handle
+        if (val == Float.POSITIVE_INFINITY) {
+            val = Float.MAX_VALUE;
+            storageWarning(new Float(Float.POSITIVE_INFINITY),
+                new Float(val));
+        } else if (val == Float.NEGATIVE_INFINITY) {
+            val = Float.MIN_VALUE + 1;
+            storageWarning(new Float(Float.NEGATIVE_INFINITY),
+                new Float(val));
+        }
+        super.setFloat(stmnt, idx, val, col);
+    }
+
+    public void setDouble(PreparedStatement stmnt, int idx, double val,
+        Column col)
+        throws SQLException {
+        // empress seems to allow INFINITY to be stored, but not retrieved,
+        // which can prove to be difficult to handle
+        if (val == Double.POSITIVE_INFINITY) {
+            val = Double.MAX_VALUE;
+            storageWarning(new Double(Double.POSITIVE_INFINITY),
+                new Double(val));
+        } else if (val == Double.NEGATIVE_INFINITY) {
+            val = Double.MIN_VALUE + 1;
+            storageWarning(new Double(Double.NEGATIVE_INFINITY),
+                new Double(val));
+        }
+        super.setDouble(stmnt, idx, val, col);
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/EmpressDictionary.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/FirebirdDictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/FirebirdDictionary.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/FirebirdDictionary.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/FirebirdDictionary.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc.sql;
+
+import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
+import org.apache.openjpa.jdbc.schema.Column;
+
+/**
+ * Dictionary for Firebird.
+ */
+public class FirebirdDictionary
+    extends InterbaseDictionary {
+
+    public FirebirdDictionary() {
+        platform = "Firebird";
+
+        // Firebird 1.5+ locking statement
+        supportsLockingWithMultipleTables = false;
+        forUpdateClause = "FOR UPDATE WITH LOCK";
+    }
+
+    public String getPlaceholderValueString(Column col) {
+        return super.getPlaceholderValueString(col)
+            + " AS " + getTypeName(col);
+    }
+
+    public void substring(SQLBuffer buf, FilterValue str, FilterValue start,
+        FilterValue end) {
+        // SUBSTRING in Firebird is of the form:
+        // SELECT SUBSTRING(SOME_COLUMN FROM 1 FOR 5)
+        buf.append("SUBSTRING(");
+        str.appendTo(buf);
+        buf.append(" FROM ");
+        start.appendTo(buf);
+        buf.append(" + 1");
+        if (end != null) {
+            buf.append(" FOR ");
+            end.appendTo(buf);
+            buf.append(" - (");
+            start.appendTo(buf);
+            buf.append(")");
+        }
+        buf.append(")");
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/FirebirdDictionary.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/FoxProDictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/FoxProDictionary.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/FoxProDictionary.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/FoxProDictionary.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,159 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc.sql;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Types;
+
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Index;
+import org.apache.openjpa.jdbc.schema.PrimaryKey;
+
+/**
+ * Dictionary for Visual FoxPro via DataDirect SequeLink
+ * and DataDirect ODBC FoxPro driver. This will not
+ * work with any other combination of JDBC/ODBC server and ODBC driver.
+ *  FoxPro has the following limitations:
+ * <ul>
+ * <li>Primary Keys and indexes cannot be created via JDBC</li>
+ * <li>Only has fixed-length char fields: all strings must be
+ * trimmed in result sets</li>
+ * <li>Does not have sufficient support for foreign keys</li>
+ * <li>ODBC driver cannot handle certain Aggregate functions.</li>
+ * <li>Locking is extremeley unreliable. Multiple clients
+ * accessing single datastore may result in concurrency
+ * data validity errors.</li>
+ * </ul>
+ */
+public class FoxProDictionary
+    extends DBDictionary {
+
+    public FoxProDictionary() {
+        platform = "Visual FoxPro";
+        joinSyntax = SYNTAX_TRADITIONAL;
+
+        supportsForeignKeys = false;
+        supportsDeferredConstraints = false;
+        maxTableNameLength = 30;
+        maxColumnNameLength = 30;
+        maxIndexNameLength = 8;
+        maxConstraintNameLength = 8;
+
+        binaryTypeName = "GENERAL";
+        blobTypeName = "GENERAL";
+        longVarbinaryTypeName = "GENERAL";
+        clobTypeName = "MEMO";
+        longVarcharTypeName = "MEMO";
+        dateTypeName = "TIMESTAMP";
+        timeTypeName = "TIMESTAMP";
+        varcharTypeName = "CHARACTER{0}";
+        bigintTypeName = "DOUBLE";
+        numericTypeName = "INTEGER";
+        smallintTypeName = "INTEGER";
+        bitTypeName = "NUMERIC(1)";
+        integerTypeName = "INTEGER";
+        tinyintTypeName = "INTEGER";
+        decimalTypeName = "DOUBLE";
+        doubleTypeName = "DOUBLE";
+        realTypeName = "DOUBLE";
+        floatTypeName = "NUMERIC(19,16)";
+
+        // the max character literal length is actually 254, but for primary
+        // keys, it is 240; default to that length so users can add PKs later
+        characterColumnSize = 240;
+    }
+
+    public String getString(ResultSet rs, int column)
+        throws SQLException {
+        // foxpro doesn't auto-truncate values.
+        String str = rs.getString(column);
+        if (str != null)
+            str = str.trim();
+        return str;
+    }
+
+    public void setNull(PreparedStatement stmnt, int idx, int colType,
+        Column col)
+        throws SQLException {
+        // ensure that blob/clob is handled with safe methods.
+        switch (colType) {
+            case Types.BLOB:
+                stmnt.setBytes(idx, null);
+                break;
+            case Types.CLOB:
+                stmnt.setString(idx, null);
+                break;
+            default:
+                super.setNull(stmnt, idx, colType, col);
+        }
+    }
+
+    protected String appendSize(Column col, String typeName) {
+        // foxpro does not like unsized column declarations.
+        if (col.getSize() == 0) {
+            if ("CHARACTER".equals(typeName))
+                col.setSize(240);
+            else if ("NUMERIC".equals(typeName))
+                col.setSize(19);
+        }
+        return super.appendSize(col, typeName);
+    }
+
+    protected String getPrimaryKeyConstraintSQL(PrimaryKey pk) {
+        // this foxpro driver combination does not support primary keys
+        return null;
+    }
+
+    public String[] getCreateIndexSQL(Index index) {
+        // foxpro JDBC access does not allow the creation of indexes
+        return new String[0];
+    }
+
+    public Column[] getColumns(DatabaseMetaData meta, String catalog,
+        String schemaName, String tableName, String columnName, Connection conn)
+        throws SQLException {
+        try {
+            Column[] cols = super.getColumns(meta, catalog, schemaName,
+                tableName, columnName, conn);
+            for (int i = 0; cols != null && i < cols.length; i++) {
+                // foxpro returns an odd type "11" code for DATETIME fields
+                if (cols[i].getType() == 11)
+                    cols[i].setType(Types.TIMESTAMP);
+                    // MEMO maps to LONGVARCHAR during reverse analysis
+                else if ("MEMO".equals(cols[i].getTypeName()))
+                    cols[i].setType(Types.CLOB);
+            }
+            return cols;
+        } catch (SQLException se) {
+            // foxpro throws an exception if the table specified in the
+            // column list is not found
+            if (se.getErrorCode() == 562)
+                return null;
+            throw se;
+        }
+    }
+
+    public PrimaryKey[] getPrimaryKeys(DatabaseMetaData meta, String catalog,
+        String schemaName, String tableName, Connection conn)
+        throws SQLException {
+        // this combination does not reliably return PK information
+        return null;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/FoxProDictionary.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/HSQLDictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/HSQLDictionary.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/HSQLDictionary.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/HSQLDictionary.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,309 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc.sql;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.Types;
+import java.util.Arrays;
+
+import org.hsqldb.Trace;
+import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.PrimaryKey;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.jdbc.schema.Unique;
+import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.util.OpenJPAException;
+import org.apache.openjpa.util.ReferentialIntegrityException;
+import serp.util.Numbers;
+
+/**
+ * Dictionary for Hypersonic SQL database.
+ */
+public class HSQLDictionary
+    extends DBDictionary {
+
+    /**
+     * Sets whether HSQL should use "CREATED CACHED TABLE" rather than
+     * "CREATE TABLE", which allows disk-based database operations.
+     */
+    public boolean cacheTables = false;
+
+    private SQLBuffer _oneBuffer = new SQLBuffer(this).append("1");
+
+    public HSQLDictionary() {
+        platform = "HSQL";
+        validationSQL = "CALL 1";
+        closePoolSQL = "SHUTDOWN";
+
+        supportsAutoAssign = true;
+        lastGeneratedKeyQuery = "CALL IDENTITY()";
+        autoAssignClause = "IDENTITY";
+        autoAssignTypeName = "INTEGER";
+        nextSequenceQuery = "SELECT NEXT VALUE FOR {0} FROM"
+            + " INFORMATION_SCHEMA.SYSTEM_SEQUENCES";
+        crossJoinClause = "JOIN";
+        requiresConditionForCrossJoin = true;
+        stringLengthFunction = "LENGTH({0})";
+        trimLeadingFunction = "LTRIM({0})";
+        trimTrailingFunction = "RTRIM({0})";
+        trimBothFunction = "LTRIM(RTRIM({0}))";
+
+        // HSQL 1.8.0 does support schema names in the table ("schema.table"),
+        // but doesn't support it for columns references ("schema.table.column")
+        useSchemaName = false;
+        supportsSelectForUpdate = false;
+        supportsSelectStartIndex = true;
+        supportsSelectEndIndex = true;
+        rangePosition = RANGE_PRE_DISTINCT;
+        supportsDeferredConstraints = false;
+
+        useGetObjectForBlobs = true;
+        blobTypeName = "VARBINARY";
+
+        supportsNullTableForGetPrimaryKeys = true;
+        supportsNullTableForGetIndexInfo = true;
+
+        requiresCastForMathFunctions = true;
+        requiresCastForComparisons = true;
+
+        reservedWordSet.addAll(Arrays.asList(new String[]{
+            "BEFORE", "BIGINT", "BINARY", "CACHED", "DATETIME", "LIMIT",
+            "LONGVARBINARY", "LONGVARCHAR", "OBJECT", "OTHER",
+            "SAVEPOINT", "TEMP", "TEXT", "TRIGGER", "TINYINT",
+            "VARBINARY", "VARCHAR_IGNORECASE",
+        }));
+    }
+
+    public int getJDBCType(int metaTypeCode, boolean lob) {
+        int type = super.getJDBCType(metaTypeCode, lob);
+        switch (type) {
+            case Types.BIGINT:
+                if (metaTypeCode == JavaTypes.BIGINTEGER)
+                    return Types.NUMERIC;
+                break;
+        }
+        return type;
+    }
+
+    public int getPreferredType(int type) {
+        switch (type) {
+            case Types.CLOB:
+                return Types.VARCHAR;
+            case Types.BLOB:
+                return Types.VARBINARY;
+            default:
+                return super.getPreferredType(type);
+        }
+    }
+
+    public String[] getAddPrimaryKeySQL(PrimaryKey pk) {
+        return new String[0];
+    }
+
+    public String[] getDropPrimaryKeySQL(PrimaryKey pk) {
+        return new String[0];
+    }
+
+    public String[] getAddColumnSQL(Column column) {
+        return new String[]{ "ALTER TABLE "
+            + getFullName(column.getTable(), false)
+            + " ADD COLUMN " + getDeclareColumnSQL(column, true) };
+    }
+
+    public String[] getCreateTableSQL(Table table) {
+        StringBuffer buf = new StringBuffer();
+        buf.append("CREATE ");
+        if (cacheTables)
+            buf.append("CACHED ");
+        buf.append("TABLE ").append(getFullName(table, false)).append(" (");
+
+        Column[] cols = table.getColumns();
+        for (int i = 0; i < cols.length; i++) {
+            if (i > 0)
+                buf.append(", ");
+            buf.append(getDeclareColumnSQL(cols[i], false));
+        }
+
+        PrimaryKey pk = table.getPrimaryKey();
+        String pkStr;
+        if (pk != null) {
+            pkStr = getPrimaryKeyConstraintSQL(pk);
+            if (pkStr != null && pkStr.length() > 0)
+                buf.append(", ").append(pkStr);
+        }
+
+        Unique[] unqs = table.getUniques();
+        String unqStr;
+        for (int i = 0; i < unqs.length; i++) {
+            unqStr = getUniqueConstraintSQL(unqs[i]);
+            if (unqStr != null)
+                buf.append(", ").append(unqStr);
+        }
+
+        buf.append(")");
+        return new String[]{ buf.toString() };
+    }
+
+    protected String getPrimaryKeyConstraintSQL(PrimaryKey pk) {
+        Column[] cols = pk.getColumns();
+        if (cols.length == 1 && cols[0].isAutoAssigned())
+            return null;
+        return super.getPrimaryKeyConstraintSQL(pk);
+    }
+
+    public boolean isSystemIndex(String name, Table table) {
+        return name.toUpperCase().startsWith("SYS_");
+    }
+
+    protected String getSequencesSQL(String schemaName, String sequenceName) {
+        StringBuffer buf = new StringBuffer();
+        buf.append("SELECT SEQUENCE_SCHEMA, SEQUENCE_NAME FROM ").
+            append("INFORMATION_SCHEMA.SYSTEM_SEQUENCES");
+        if (schemaName != null || sequenceName != null)
+            buf.append(" WHERE ");
+        if (schemaName != null) {
+            buf.append("SEQUENCE_SCHEMA = ?");
+            if (sequenceName != null)
+                buf.append(" AND ");
+        }
+        if (sequenceName != null)
+            buf.append("SEQUENCE_NAME = ?");
+        return buf.toString();
+    }
+
+    public SQLBuffer toOperation(String op, SQLBuffer selects, SQLBuffer from,
+        SQLBuffer where, SQLBuffer group, SQLBuffer having, SQLBuffer order,
+        boolean distinct, boolean forUpdate, long start, long end) {
+        // hsql requires ordering when limit is used
+        if ((start != 0 || end != Long.MAX_VALUE)
+            && (order == null || order.isEmpty()))
+            order = _oneBuffer;
+        return super.toOperation(op, selects, from, where, group, having,
+            order, distinct, forUpdate, start, end);
+    }
+
+    public Column[] getColumns(DatabaseMetaData meta, String catalog,
+        String schemaName, String tableName, String columnName, Connection conn)
+        throws SQLException {
+        Column[] cols = super.getColumns(meta, catalog, schemaName, tableName,
+            columnName, conn);
+
+        for (int i = 0; cols != null && i < cols.length; i++)
+            if ("BOOLEAN".equalsIgnoreCase(cols[i].getTypeName()))
+                cols[i].setType(Types.BIT);
+        return cols;
+    }
+
+    public void setLong(PreparedStatement stmnt, int idx, long val, Column col)
+        throws SQLException {
+        if (val == Long.MIN_VALUE) {
+            val = Long.MIN_VALUE + 1;
+            storageWarning(Numbers.valueOf(Long.MIN_VALUE),
+                Numbers.valueOf(val));
+        }
+        super.setLong(stmnt, idx, val, col);
+    }
+
+    public void setBigDecimal(PreparedStatement stmnt, int idx, BigDecimal val,
+        Column col)
+        throws SQLException {
+        // hsql can't compare a BigDecimal equal to any other type, so try
+        // to set type based on column
+        int type = (val == null || col == null) ? JavaTypes.BIGDECIMAL
+            : col.getJavaType();
+        switch (type) {
+            case JavaTypes.DOUBLE:
+            case JavaTypes.DOUBLE_OBJ:
+                setDouble(stmnt, idx, val.doubleValue(), col);
+                break;
+            case JavaTypes.FLOAT:
+            case JavaTypes.FLOAT_OBJ:
+                setDouble(stmnt, idx, val.floatValue(), col);
+                break;
+            default:
+                super.setBigDecimal(stmnt, idx, val, col);
+        }
+    }
+
+    protected void appendSelectRange(SQLBuffer buf, long start, long end) {
+        // HSQL doesn't parameters in range
+        buf.append(" LIMIT ").append(String.valueOf(start)).append(" ");
+        if (end == Long.MAX_VALUE)
+            buf.append(String.valueOf(0));
+        else
+            buf.append(String.valueOf(end - start));
+    }
+
+    public void substring(SQLBuffer buf, FilterValue str, FilterValue start,
+        FilterValue end) {
+        buf.append(substringFunctionName).append("((");
+        str.appendTo(buf);
+        buf.append("), (");
+        start.appendTo(buf);
+        buf.append(" + 1)");
+        if (end != null) {
+            buf.append(", (");
+            appendNumericCast(buf, end);
+            buf.append(" - (");
+            appendNumericCast(buf, start);
+            buf.append("))");
+        }
+        buf.append(")");
+    }
+
+    public void indexOf(SQLBuffer buf, FilterValue str, FilterValue find,
+        FilterValue start) {
+        buf.append("(LOCATE(");
+        find.appendTo(buf);
+        buf.append(", ");
+        str.appendTo(buf);
+        if (start != null) {
+            buf.append(", (");
+            start.appendTo(buf);
+            buf.append(" + 1)");
+        }
+        buf.append(") - 1)");
+    }
+
+    public String getPlaceholderValueString(Column col) {
+        String type = getTypeName(col.getType());
+        int idx = type.indexOf("{0}");
+        if (idx != -1) {
+            String pre = type.substring(0, idx);
+            if (type.length() > idx + 3)
+                type = pre + type.substring(idx + 3);
+            else
+                type = pre;
+        }
+        return "NULL AS " + type;
+    }
+
+    public OpenJPAException newStoreException(String msg, SQLException[] causes,
+        Object failed) {
+        OpenJPAException ke = super.newStoreException(msg, causes, failed);
+        if (ke instanceof ReferentialIntegrityException
+            && causes[0].getErrorCode() == -Trace.VIOLATION_OF_UNIQUE_INDEX) {
+            ((ReferentialIntegrityException) ke).setIntegrityViolation
+                (ReferentialIntegrityException.IV_UNIQUE);
+        }
+        return ke;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/HSQLDictionary.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,253 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc.sql;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.Arrays;
+import java.util.Collection;
+
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.schema.Index;
+import org.apache.openjpa.jdbc.schema.PrimaryKey;
+import org.apache.openjpa.jdbc.schema.Table;
+import org.apache.openjpa.lib.util.ReferenceHashSet;
+
+/**
+ * Dictionary for Informix database. Notable features:
+ * <ul>
+ * <li>Informix does not allow pessimistic locking on scrollable result
+ * sets.</li>
+ * <li>SET LOCK MODE TO WAIT N statements are issued to wait on locks. See
+ * {@link #lockWaitSeconds} and {@link #lockModeEnabled}.</li>
+ * <li>LOCK MODE ROW is used by default for table creation to allow the
+ * maximum concurrency.</li>
+ * </ul>
+ */
+public class InformixDictionary
+    extends DBDictionary {
+
+    /**
+     * If true, then we will issue a "SET LOCK MODE TO WAIT N"
+     * statement whenever we create a {@link Connection}, in order
+     * allow waiting on locks.
+     */
+    public boolean lockModeEnabled = false;
+
+    /**
+     * If {@link #lockModeEnabled} is <code>true</code>, then this
+     * parameter specifies the number of seconds we will wait to
+     * obtain a lock for inserts and pessimistic locking.
+     */
+    public int lockWaitSeconds = 30;
+
+    /**
+     * Informix JDBC metadata for all known drivers returns with the
+     * table catalog and the table schema name swapped. A <code>true</code>
+     * value for this property indicates that they should be reversed.
+     */
+    public boolean swapSchemaAndCatalog = true;
+
+    // weak set of connections we've already executed lock mode sql on
+    private final Collection _seenConnections = new ReferenceHashSet
+        (ReferenceHashSet.WEAK);
+
+    public InformixDictionary() {
+        platform = "Informix";
+        validationSQL = "SELECT FIRST 1 CURRENT TIMESTAMP "
+            + "FROM informix.systables";
+
+        supportsAutoAssign = true;
+        autoAssignTypeName = "serial";
+        lastGeneratedKeyQuery = "SELECT FIRST 1 DBINFO('sqlca.sqlerrd1') "
+            + "FROM informix.systables";
+
+        // informix actually does support deferred constraints, but not
+        // in the table definition; deferred constraints can be activated by
+        // invoking "set constraints all deferred" on the connection, which
+        // we don't do yet
+        supportsDeferredConstraints = false;
+        constraintNameMode = CONS_NAME_AFTER;
+
+        maxTableNameLength = 18;
+        maxColumnNameLength = 18;
+        maxIndexNameLength = 18;
+        maxConstraintNameLength = 18;
+
+        // Informix uses a non-standard ":" to separate schema and table names
+        catalogSeparator = ":";
+
+        // informix supports "CLOB" type, but any attempt to insert
+        // into them raises: "java.sql.SQLException: Can't convert fromnull"
+        useGetStringForClobs = true;
+        longVarcharTypeName = "TEXT";
+        clobTypeName = "TEXT";
+        smallintTypeName = "INT8";
+        tinyintTypeName = "INT8";
+        floatTypeName = "FLOAT";
+        bitTypeName = "BOOLEAN";
+        blobTypeName = "BYTE";
+        doubleTypeName = "NUMERIC(32,20)";
+        dateTypeName = "DATE";
+        timestampTypeName = "DATE";
+        doubleTypeName = "NUMERIC(32,20)";
+        floatTypeName = "REAL";
+        bigintTypeName = "NUMERIC(32,0)";
+        doubleTypeName = "DOUBLE PRECISION";
+        fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
+            "BYTE", "DOUBLE PRECISION", "INTERVAL", "SMALLFLOAT", "TEXT",
+            "INT8",
+        }));
+
+        supportsQueryTimeout = false;
+        supportsMultipleNontransactionalResultSets = false;
+        supportsLockingWithDistinctClause = false;
+        supportsLockingWithMultipleTables = false;
+        supportsLockingWithOrderClause = false;
+
+        // the informix JDBC drivers have problems with using the
+        // schema name in reflection on columns and tables
+        supportsSchemaForGetColumns = false;
+        supportsSchemaForGetTables = false;
+    }
+
+    public void connectedConfiguration(Connection conn)
+        throws SQLException {
+        super.connectedConfiguration(conn);
+        if (driverVendor == null) {
+            DatabaseMetaData meta = conn.getMetaData();
+            if ("Informix".equalsIgnoreCase(meta.getDriverName()))
+                driverVendor = VENDOR_DATADIRECT;
+            else
+                driverVendor = VENDOR_OTHER;
+        }
+    }
+
+    public Column[] getColumns(DatabaseMetaData meta, String catalog,
+        String schemaName, String tableName, String columnName, Connection conn)
+        throws SQLException {
+        Column[] cols = super.getColumns(meta, catalog, schemaName, tableName,
+            columnName, conn);
+
+        // treat logvarchar as clob
+        for (int i = 0; cols != null && i < cols.length; i++)
+            if (cols[i].getType() == Types.LONGVARCHAR)
+                cols[i].setType(Types.CLOB);
+        return cols;
+    }
+
+    public Column newColumn(ResultSet colMeta)
+        throws SQLException {
+        Column col = super.newColumn(colMeta);
+        if (swapSchemaAndCatalog)
+            col.setSchemaName(colMeta.getString("TABLE_CAT"));
+        return col;
+    }
+
+    public PrimaryKey newPrimaryKey(ResultSet pkMeta)
+        throws SQLException {
+        PrimaryKey pk = super.newPrimaryKey(pkMeta);
+        if (swapSchemaAndCatalog)
+            pk.setSchemaName(pkMeta.getString("TABLE_CAT"));
+        return pk;
+    }
+
+    public Index newIndex(ResultSet idxMeta)
+        throws SQLException {
+        Index idx = super.newIndex(idxMeta);
+        if (swapSchemaAndCatalog)
+            idx.setSchemaName(idxMeta.getString("TABLE_CAT"));
+        return idx;
+    }
+
+    public void setBoolean(PreparedStatement stmnt, int idx, boolean val,
+        Column col)
+        throws SQLException {
+        // informix actually requires that a boolean be set: it cannot
+        // handle a numeric argument
+        stmnt.setBoolean(idx, val);
+    }
+
+    public String[] getCreateTableSQL(Table table) {
+        String[] create = super.getCreateTableSQL(table);
+        create[0] = create[0] + " LOCK MODE ROW";
+        return create;
+    }
+
+    public String[] getAddPrimaryKeySQL(PrimaryKey pk) {
+        String pksql = getPrimaryKeyConstraintSQL(pk);
+        if (pksql == null)
+            return new String[0];
+        return new String[]{ "ALTER TABLE "
+            + getFullName(pk.getTable(), false) + " ADD CONSTRAINT " + pksql };
+    }
+
+    public String[] getAddForeignKeySQL(ForeignKey fk) {
+        String fksql = getForeignKeyConstraintSQL(fk);
+        if (fksql == null)
+            return new String[0];
+        return new String[]{ "ALTER TABLE "
+            + getFullName(fk.getTable(), false) + " ADD CONSTRAINT " + fksql };
+    }
+
+    public boolean supportsRandomAccessResultSet(Select sel,
+        boolean forUpdate) {
+        return !forUpdate && !sel.isLob()
+            && super.supportsRandomAccessResultSet(sel, forUpdate);
+    }
+
+    public Connection decorate(Connection conn)
+        throws SQLException {
+        conn = super.decorate(conn);
+
+        // if we haven't already done so, initialize the lock mode of the
+        // connection
+        if (lockModeEnabled && _seenConnections.add(conn)) {
+            String sql = "SET LOCK MODE TO WAIT";
+            if (lockWaitSeconds > 0)
+                sql = sql + " " + lockWaitSeconds;
+
+            Statement stmnt = null;
+            try {
+                stmnt = conn.createStatement();
+                stmnt.executeUpdate(sql);
+            } catch (SQLException se) {
+                throw SQLExceptions.getStore(se, this);
+            } finally {
+                if (stmnt != null)
+                    try {
+                        stmnt.close();
+                    } catch (SQLException se) {
+                    }
+            }
+        }
+
+        // the datadirect driver requires that we issue a rollback before using
+        // each connection
+        if (VENDOR_DATADIRECT.equalsIgnoreCase(driverVendor))
+            try {
+                conn.rollback();
+            } catch (SQLException se) {
+            }
+        return conn;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InterbaseDictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InterbaseDictionary.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InterbaseDictionary.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InterbaseDictionary.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,115 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc.sql;
+
+import java.sql.Types;
+
+import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
+import org.apache.openjpa.jdbc.schema.Column;
+import org.apache.openjpa.jdbc.schema.Index;
+import org.apache.openjpa.lib.util.Localizer;
+import org.apache.openjpa.util.StoreException;
+
+/**
+ * Dictionary for Borland Interbase.
+ */
+public class InterbaseDictionary
+    extends DBDictionary {
+
+    private static final Localizer _loc = Localizer.forPackage
+        (InterbaseDictionary.class);
+
+    public InterbaseDictionary() {
+        platform = "Borland Interbase";
+        validationSQL = "SELECT 1 FROM RDB$DATABASE";
+        supportsDeferredConstraints = false;
+
+        useGetStringForClobs = true;
+        useSetStringForClobs = true;
+        useGetBytesForBlobs = true;
+        useSetBytesForBlobs = true;
+
+        // the JDBC driver claims 31, but that causes exceptions
+        maxTableNameLength = 30;
+
+        bigintTypeName = "NUMERIC(18,0)";
+        integerTypeName = "INTEGER";
+        doubleTypeName = "DOUBLE PRECISION";
+        charTypeName = "CHAR(1)";
+        blobTypeName = "BLOB";
+        clobTypeName = "BLOB SUB_TYPE 1";
+        bitTypeName = "SMALLINT";
+        smallintTypeName = "SMALLINT";
+        tinyintTypeName = "SMALLINT";
+
+        // no support for lower-casing or finding the length of strings
+        // (although it can be added to the database; see
+        // http://bdn.borland.com/article/0,1410,27563,00.html )
+        toLowerCaseFunction = null;
+        stringLengthFunction = null;
+    }
+
+    protected String getTableNameForMetadata(String tableName) {
+        return (tableName == null) ? "%"
+            : super.getTableNameForMetadata(tableName);
+    }
+
+    protected String getColumnNameForMetadata(String columnName) {
+        return (columnName == null) ? "%"
+            : super.getColumnNameForMetadata(columnName);
+    }
+
+    protected String appendSize(Column col, String typeName) {
+        if (col.isPrimaryKey() && col.getType() == Types.VARCHAR) {
+            // reduce size of varchar primary key cols proportional to the
+            // number of cols, because interbase caps the total pk size
+            int numKeys = 1;
+            if (col.getTable() != null
+                && col.getTable().getPrimaryKey() != null)
+                numKeys = col.getTable().getPrimaryKey().getColumns().length;
+            col.setSize(Math.min(col.getSize(), 200 / numKeys));
+        } else if (col.getType() == Types.VARCHAR && col.getSize() > 200
+            && col.getTable() != null) {
+            // indexed varchar cols have to be <= 250 chars
+            Index[] idx = col.getTable().getIndexes();
+            for (int i = 0; i < idx.length; i++) {
+                if (idx[i].containsColumn(col)) {
+                    col.setSize(Math.min(col.getSize(), 200));
+                    break;
+                }
+            }
+        }
+        return super.appendSize(col, typeName);
+    }
+
+    public void indexOf(SQLBuffer buf, FilterValue str, FilterValue find,
+        FilterValue start) {
+        throw new StoreException(_loc.get("indexof-not-supported", platform));
+    }
+
+    public void substring(SQLBuffer buf, FilterValue str, FilterValue start,
+        FilterValue end) {
+        throw new StoreException(_loc.get("substring-not-supported",
+            platform));
+    }
+
+    public String[] getDropColumnSQL(Column column) {
+        // Interbase uses "ALTER TABLE DROP <COLUMN_NAME>" rather than the
+        // usual "ALTER TABLE DROP COLUMN <COLUMN_NAME>"
+        return new String[]{ "ALTER TABLE "
+            + getFullName(column.getTable(), false) + " DROP " + column };
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InterbaseDictionary.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/JDataStoreDictionary.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/JDataStoreDictionary.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/JDataStoreDictionary.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/JDataStoreDictionary.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc.sql;
+
+import java.sql.SQLException;
+import java.util.Arrays;
+
+import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
+import org.apache.openjpa.util.OpenJPAException;
+import org.apache.openjpa.util.ReferentialIntegrityException;
+
+/**
+ * Dictionary for Borland JDataStore
+ */
+public class JDataStoreDictionary
+    extends DBDictionary {
+
+    public JDataStoreDictionary() {
+        platform = "Borland JDataStore";
+        joinSyntax = SYNTAX_TRADITIONAL;
+
+        supportsDeferredConstraints = false;
+        allowsAliasInBulkClause = false;
+
+        maxTableNameLength = 31;
+        maxColumnNameLength = 31;
+        maxIndexNameLength = 31;
+        maxConstraintNameLength = 31;
+
+        useGetStringForClobs = true;
+        useSetStringForClobs = true;
+        useGetBytesForBlobs = true;
+        blobTypeName = "VARBINARY";
+        clobTypeName = "VARCHAR";
+
+        // it is possible to use a FOR UPDATE clause with JDataStore,
+        // but the actual row won't wind up being locked
+        supportsLockingWithDistinctClause = false;
+        supportsQueryTimeout = false;
+
+        // there is no build-in function for getting the last generated
+        // key in JDataStore; using MAX will have to suffice
+        supportsAutoAssign = true;
+        lastGeneratedKeyQuery = "SELECT MAX({0}) FROM {1}";
+        autoAssignClause = "AUTOINCREMENT";
+
+        fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
+            "SHORT", "INT", "LONG", "DOUBLE PRECISION", "BOOLEAN",
+        }));
+
+        searchStringEscape = "";
+    }
+
+    public void substring(SQLBuffer buf, FilterValue str, FilterValue start,
+        FilterValue end) {
+        buf.append("SUBSTRING(");
+        str.appendTo(buf);
+        buf.append(" FROM (");
+        start.appendTo(buf);
+        buf.append(" + 1) FOR (");
+        if (end == null) {
+            buf.append("CHAR_LENGTH(");
+            str.appendTo(buf);
+            buf.append(")");
+        } else
+            end.appendTo(buf);
+        buf.append(" - (");
+        start.appendTo(buf);
+        buf.append(")))");
+    }
+
+    public void indexOf(SQLBuffer buf, FilterValue str, FilterValue find,
+        FilterValue start) {
+        buf.append("(POSITION(");
+        find.appendTo(buf);
+        buf.append(" IN ");
+        if (start != null)
+            substring(buf, str, start, null);
+        else
+            str.appendTo(buf);
+        buf.append(") - 1");
+        if (start != null) {
+            buf.append(" + ");
+            start.appendTo(buf);
+        }
+        buf.append(")");
+    }
+
+    public OpenJPAException newStoreException(String msg, SQLException[] causes,
+        Object failed) {
+        OpenJPAException ke = super.newStoreException(msg, causes, failed);
+        if (ke instanceof ReferentialIntegrityException
+            && causes[0].getMessage().indexOf("Duplicate key value for") > -1) {
+            ((ReferentialIntegrityException) ke).setIntegrityViolation
+                (ReferentialIntegrityException.IV_UNIQUE);
+        }
+        return ke;
+    }
+}

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/JDataStoreDictionary.java
------------------------------------------------------------------------------
    svn:executable = *

Added: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Join.java
URL: http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Join.java?rev=423615&view=auto
==============================================================================
--- incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Join.java (added)
+++ incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Join.java Wed Jul 19 14:34:44 2006
@@ -0,0 +1,151 @@
+/*
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed 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.jdbc.sql;
+
+import org.apache.openjpa.jdbc.schema.ForeignKey;
+import org.apache.openjpa.jdbc.schema.Table;
+
+/**
+ * Represents a SQL join.
+ *
+ * @author Abe White
+ */
+public class Join
+    implements Cloneable, JoinSyntaxes {
+
+    public static final int TYPE_INNER = 0;
+    public static final int TYPE_OUTER = 1;
+    public static final int TYPE_CROSS = 2;
+
+    private int _type = TYPE_INNER;
+
+    private int _alias1;
+    private int _alias2;
+    private Table _table1;
+    private Table _table2;
+    private ForeignKey _fk;
+    private boolean _inverse;
+
+    /**
+     * Constructor for inner and outer joins.
+     */
+    Join(Table table1, int alias1, Table table2, int alias2, ForeignKey fk,
+        boolean inverse) {
+        _table1 = table1;
+        _alias1 = alias1;
+        _table2 = table2;
+        _alias2 = alias2;
+        _fk = fk;
+        _inverse = inverse;
+    }
+
+    /**
+     * Private default constructor.
+     */
+    private Join() {
+    }
+
+    public int getType() {
+        return _type;
+    }
+
+    public void setType(int type) {
+        _type = type;
+    }
+
+    public String getAlias1() {
+        return SelectImpl.toAlias(_alias1);
+    }
+
+    public String getAlias2() {
+        return SelectImpl.toAlias(_alias2);
+    }
+
+    int getIndex1() {
+        return _alias1;
+    }
+
+    int getIndex2() {
+        return _alias2;
+    }
+
+    public Table getTable1() {
+        return _table1;
+    }
+
+    public Table getTable2() {
+        return _table2;
+    }
+
+    public ForeignKey getForeignKey() {
+        return _fk;
+    }
+
+    public boolean isForeignKeyInversed() {
+        return _inverse;
+    }
+
+    /**
+     * Return a join that is this join in reverse.
+     */
+    public Join reverse() {
+        Join join = new Join();
+        join._type = _type;
+        join._table1 = _table2;
+        join._alias1 = _alias2;
+        join._table2 = _table1;
+        join._alias2 = _alias1;
+        join._fk = _fk;
+        join._inverse = !_inverse;
+        return join;
+    }
+
+    public int hashCode() {
+        return _alias1 ^ _alias2;
+    }
+
+    public boolean equals(Object other) {
+        if (other == this)
+            return true;
+        if (!(other instanceof Join))
+            return false;
+
+        Join j = (Join) other;
+        return (_alias1 == j._alias1 && _alias2 == j._alias2)
+            || (_alias1 == j._alias2 && _alias2 == j._alias1);
+    }
+
+    public String toString() {
+        String typeString;
+        if (_type == TYPE_CROSS)
+            typeString = "cross";
+        else if (_type == TYPE_INNER)
+            typeString = "inner";
+        else
+            typeString = "outer";
+        return "<" + System.identityHashCode(this) + "> t"
+            + _alias1 + "->t" + _alias2 + " (" + typeString + ")";
+    }
+
+    public Object clone() {
+        try {
+            return super.clone();
+        } catch (Exception e) {
+            return null;
+        }
+    }
+}
+

Propchange: incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/Join.java
------------------------------------------------------------------------------
    svn:executable = *