You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by fa...@apache.org on 2010/08/19 06:19:40 UTC
svn commit: r987013 - in /openjpa/trunk:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/schema/
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/
openjpa-persistence-jdbc/src/test/j...
Author: faywang
Date: Thu Aug 19 04:19:39 2010
New Revision: 987013
URL: http://svn.apache.org/viewvc?rev=987013&view=rev
Log:
OPENJPA-735: OpenJPA support for SolidDB
Modified:
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/DBDictionary.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SolidDBDictionary.java
openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/localizer.properties
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/GroupingTestCase.java
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=987013&r1=987012&r2=987013&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 Aug 19 04:19:39 2010
@@ -558,7 +558,7 @@ public class SchemaTool {
if (dbTable != null) {
idx = findIndex(dbTable, idxs[k]);
if (idx == null) {
- if (createIndex(idxs[k], dbTable))
+ if (createIndex(idxs[k], dbTable, tabs[j].getUniques()))
dbTable.importIndex(idxs[k]);
else
_log.warn(_loc.get("add-index", idxs[k],
@@ -953,7 +953,7 @@ public class SchemaTool {
*/
public boolean createTable(Table table)
throws SQLException {
- return executeSQL(_dict.getCreateTableSQL(table));
+ return executeSQL(_dict.getCreateTableSQL(table, _db));
}
/**
@@ -993,10 +993,15 @@ public class SchemaTool {
*/
public boolean createIndex(Index idx, Table table)
throws SQLException {
+ return createIndex(idx, table, null);
+ }
+
+ public boolean createIndex(Index idx, Table table, Unique[] uniques)
+ throws SQLException {
// Informix will automatically create a unique index for the
// primary key, so don't create another index again
- if (!_dict.needsToCreateIndex(idx,table))
+ if (!_dict.needsToCreateIndex(idx,table,uniques))
return false;
int max = _dict.maxIndexesPerTable;
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=987013&r1=987012&r2=987013&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 Aug 19 04:19:39 2010
@@ -87,6 +87,7 @@ import org.apache.openjpa.jdbc.schema.In
import org.apache.openjpa.jdbc.schema.NameSet;
import org.apache.openjpa.jdbc.schema.PrimaryKey;
import org.apache.openjpa.jdbc.schema.Schema;
+import org.apache.openjpa.jdbc.schema.SchemaGroup;
import org.apache.openjpa.jdbc.schema.Sequence;
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.jdbc.schema.Unique;
@@ -3302,6 +3303,14 @@ public class DBDictionary
* Return a series of SQL statements to create the given table, complete
* with columns. Indexes and constraints will be created separately.
*/
+ public String[] getCreateTableSQL(Table table, SchemaGroup group) {
+ return getCreateTableSQL(table);
+ }
+
+ /**
+ * Return a series of SQL statements to create the given table, complete
+ * with columns. Indexes and constraints will be created separately.
+ */
public String[] getCreateTableSQL(Table table) {
StringBuilder buf = new StringBuilder();
String tableName = checkNameLength(getFullName(table, false),
@@ -4525,10 +4534,7 @@ public class DBDictionary
String query = lastGeneratedKeyQuery;
if (query.indexOf('{') != -1) // only if the token is in the string
{
- query = MessageFormat.format(query, new Object[]{
- toDBName(col.getIdentifier()), getFullName(col.getTable(), false),
- getGeneratedKeySequenceName(col),
- });
+ query = getGenKeySeqName(query, col);
}
PreparedStatement stmnt = prepareStatement(conn, query);
@@ -4545,6 +4551,13 @@ public class DBDictionary
}
}
+ protected String getGenKeySeqName(String query, Column col) {
+ return MessageFormat.format(query, new Object[]{
+ toDBName(col.getIdentifier()), getFullName(col.getTable(), false),
+ getGeneratedKeySequenceName(col),
+ });
+ }
+
/**
* Return the sequence name used by databases for the given autoassigned
* column. This is only used by databases that require an explicit name
@@ -5206,6 +5219,10 @@ public class DBDictionary
return false;
}
+ public boolean needsToCreateIndex(Index idx, Table table, Unique[] uniques) {
+ return needsToCreateIndex(idx, table);
+ }
+
public boolean needsToCreateIndex(Index idx, Table table) {
return true;
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SolidDBDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SolidDBDictionary.java?rev=987013&r1=987012&r2=987013&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SolidDBDictionary.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SolidDBDictionary.java Thu Aug 19 04:19:39 2010
@@ -21,6 +21,7 @@ package org.apache.openjpa.jdbc.sql;
import java.math.BigDecimal;
import java.sql.PreparedStatement;
import java.sql.SQLException;
+import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -28,13 +29,19 @@ import java.util.List;
import org.apache.commons.lang.StringUtils;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.kernel.exps.FilterValue;
+import org.apache.openjpa.jdbc.kernel.exps.Lit;
import org.apache.openjpa.jdbc.schema.Column;
import org.apache.openjpa.jdbc.schema.Index;
import org.apache.openjpa.jdbc.schema.PrimaryKey;
+import org.apache.openjpa.jdbc.schema.Schema;
+import org.apache.openjpa.jdbc.schema.SchemaGroup;
+import org.apache.openjpa.jdbc.schema.Sequence;
import org.apache.openjpa.jdbc.schema.Table;
import org.apache.openjpa.jdbc.schema.Unique;
+import org.apache.openjpa.kernel.exps.Literal;
import org.apache.openjpa.lib.util.Localizer;
import org.apache.openjpa.meta.JavaTypes;
+import org.apache.openjpa.util.UserException;
/**
* Dictionary for SolidDB database.
@@ -75,7 +82,7 @@ public class SolidDBDictionary
public boolean useTriggersForAutoAssign = true;
/**
- * The global sequence name to use for autoassign simulation.
+ * The global sequence name to use for auto-assign simulation.
*/
public String autoAssignSequenceName = null;
@@ -84,6 +91,11 @@ public class SolidDBDictionary
* trigger name for backwards compatibility.
*/
public boolean openjpa3GeneratedKeyNames = false;
+
+ /**
+ * Possible values for LockingMode are "PESSIMISTIC" and "OPTIMISTIC"
+ */
+ public String lockingMode = null;
private static final Localizer _loc = Localizer.forPackage
@@ -111,6 +123,10 @@ public class SolidDBDictionary
currentDateFunction = "CURDATE()";
currentTimeFunction = "CURTIME()";
currentTimestampFunction = "NOW()";
+ lastGeneratedKeyQuery = "SELECT {0}.CURRENT";
+ sequenceSQL = "SELECT SEQUENCE_SCHEMA, SEQUENCE_NAME FROM SYS_SEQUENCES";
+ sequenceSchemaSQL = "SEQSCHEMA = ?";
+ sequenceNameSQL = "SEQNAME = ?";
reservedWordSet.addAll(Arrays.asList(new String[]{
"BIGINT", "BINARY", "DATE", "TIME",
@@ -119,7 +135,15 @@ public class SolidDBDictionary
}
@Override
- public String[] getCreateTableSQL(Table table) {
+ public void endConfiguration() {
+ super.endConfiguration();
+ if (useTriggersForAutoAssign) {
+ supportsAutoAssign = true;
+ }
+ }
+
+ @Override
+ public String[] getCreateTableSQL(Table table, SchemaGroup group) {
StringBuilder buf = new StringBuilder();
buf.append("CREATE TABLE ").append(getFullName(table, false)).append(" (");
Column[] cols = table.getColumns();
@@ -151,7 +175,26 @@ public class SolidDBDictionary
else
buf.append("DISK");
- String[] create = new String[]{ buf.toString() };
+ String[] create = null;
+ if (lockingMode != null) {
+ StringBuilder buf1 = new StringBuilder();
+ if (lockingMode.equalsIgnoreCase("PESSIMISTIC")) {
+ buf1.append("ALTER TABLE ").append(getFullName(table, false)).
+ append(" SET PESSIMISTIC");
+ } else if (lockingMode.equalsIgnoreCase("OPTIMISTIC")){
+ buf1.append("ALTER TABLE ").append(getFullName(table, false)).
+ append(" SET OPTIMISTIC");
+ } else
+ throw new UserException(_loc.get("invalid-locking-mode", lockingMode));
+
+ create = new String[2];
+ create[0] = buf.toString();
+ create[1] = buf1.toString();
+ } else {
+ create = new String[1];
+ create[0] = buf.toString();
+ }
+
if (!useTriggersForAutoAssign)
return create;
@@ -163,14 +206,11 @@ public class SolidDBDictionary
if (seqs == null)
seqs = new ArrayList(4);
- seq = autoAssignSequenceName;
- if (seq == null) {
- if (openjpa3GeneratedKeyNames)
- seq = getOpenJPA3GeneratedKeySequenceName(cols[i]);
- else
- seq = getGeneratedKeySequenceName(cols[i]);
- seqs.add("CREATE SEQUENCE " + seq);
- }
+ seq = getAutoGenSeqName(cols[i]);
+ if (sequenecExists(table.getSchemaIdentifier().getName(), seq, group))
+ seqs.add("DROP SEQUENCE " + seq);
+ seqs.add("CREATE SEQUENCE " + seq);
+
if (openjpa3GeneratedKeyNames)
trig = getOpenJPA3GeneratedKeyTriggerName(cols[i]);
else
@@ -189,6 +229,7 @@ public class SolidDBDictionary
+ " ON " + toDBName(table.getIdentifier())
+ " BEFORE INSERT REFERENCING NEW " + toDBName(cols[i].getIdentifier())
+ " AS NEW_COL1 BEGIN EXEC SEQUENCE " + seq + " NEXT INTO NEW_COL1; END");
+
}
if (seqs == null)
return create;
@@ -201,6 +242,23 @@ public class SolidDBDictionary
return sql;
}
+ protected boolean sequenecExists(String schemaName, String seqName, SchemaGroup group) {
+ Schema[] schemas = group.getSchemas();
+ for (int i = 0; i < schemas.length; i++) {
+ String dbSchemaName = schemas[i].getIdentifier().getName();
+ if (schemaName != null && !schemaName.equalsIgnoreCase(dbSchemaName))
+ continue;
+
+ Sequence[] seqs = schemas[i].getSequences();
+ for (int j = 0; j < seqs.length; j++) {
+ String dbSeqName = seqs[j].getName();
+ if (dbSeqName != null && dbSeqName.equalsIgnoreCase(seqName))
+ return true;
+ }
+ }
+ return false;
+ }
+
/**
* Trigger name for simulating auto-assign values on the given column.
*/
@@ -230,6 +288,22 @@ public class SolidDBDictionary
getSchemaGroup(), maxTableNameLength, true));
}
+ protected String getAutoGenSeqName(Column col) {
+ String seqName = autoAssignSequenceName;
+ if (seqName == null) {
+ if (openjpa3GeneratedKeyNames)
+ seqName = getOpenJPA3GeneratedKeySequenceName(col);
+ else
+ seqName = getGeneratedKeySequenceName(col);
+ }
+ return seqName;
+ }
+
+ @Override
+ protected String getGenKeySeqName(String query, Column col) {
+ return MessageFormat.format(query, new Object[]{getAutoGenSeqName(col)});
+ }
+
@Override
public String convertSchemaCase(DBIdentifier objectName) {
if (objectName != null && objectName.getName() == null)
@@ -303,6 +377,23 @@ public class SolidDBDictionary
}
@Override
+ public boolean isSystemSequence(DBIdentifier name, DBIdentifier schema,
+ boolean targetSchema) {
+ if (super.isSystemSequence(name, schema, targetSchema))
+ return true;
+ String schemaName = DBIdentifier.isNull(schema) ? null : schema.getName();
+ boolean startsWith_SYSTEM = schema.isDelimited() ? schemaName.startsWith("\"_SYSTEM") :
+ schemaName.startsWith("_SYSTEM");
+
+ String seqName = DBIdentifier.isNull(name) ? null : name.getName();
+ boolean startsWithSYS_SEQ_ = name.isDelimited() ? seqName.startsWith("\"SYS_SEQ_") :
+ seqName.startsWith("SYS_SEQ_");
+ if (startsWith_SYSTEM && startsWithSYS_SEQ_)
+ return true;
+ return false;
+ }
+
+ @Override
public void setBigDecimal(PreparedStatement stmnt, int idx, BigDecimal val,
Column col) throws SQLException {
int type = (val == null || col == null) ? JavaTypes.BIGDECIMAL
@@ -347,13 +438,90 @@ public class SolidDBDictionary
}
@Override
- public boolean needsToCreateIndex(Index idx, Table table) {
+ public boolean needsToCreateIndex(Index idx, Table table, Unique[] uniques) {
// SolidDB will automatically create a unique index for the
// constraint, so don't create another index again
PrimaryKey pk = table.getPrimaryKey();
if (pk != null && idx.columnsMatch(pk.getColumns()))
return false;
- return true;
+
+ // If table1 has constraints on column (a, b), an explicit index on (a)
+ // will cause duplicate index error from SolidDB
+ Column[] icols = idx.getColumns();
+ boolean isDuplicate = false;
+ boolean mayBeDuplicate = false;
+ for (int i = 0; i < uniques.length; i++) {
+ Column[] ucols = uniques[i].getColumns();
+ if (ucols.length < icols.length)
+ continue;
+ for (int j = 0, k = 0; j < ucols.length && k < icols.length; j++, k++) {
+ if (mayBeDuplicate && ucols[j].getQualifiedPath().equals(icols[k].getQualifiedPath())) {
+ if (k == icols.length - 1) {
+ isDuplicate = true;
+ } else {
+ mayBeDuplicate = true;
+ }
+ } else
+ mayBeDuplicate = false;
+ }
+ if (isDuplicate)
+ break;
+ }
+ return isDuplicate;
+ }
+
+ @Override
+ protected String getSequencesSQL(String schemaName, String sequenceName) {
+ return getSequencesSQL(DBIdentifier.newSchema(schemaName),
+ DBIdentifier.newSequence(sequenceName));
}
+ @Override
+ protected String getSequencesSQL(DBIdentifier schemaName, DBIdentifier sequenceName) {
+ StringBuilder buf = new StringBuilder();
+ buf.append(sequenceSQL);
+ if (!DBIdentifier.isNull(schemaName) || !DBIdentifier.isNull(sequenceName))
+ buf.append(" WHERE ");
+ if (!DBIdentifier.isNull(schemaName)) {
+ buf.append(sequenceSchemaSQL);
+ if (!DBIdentifier.isNull(sequenceName))
+ buf.append(" AND ");
+ }
+ if (!DBIdentifier.isNull(sequenceName))
+ buf.append(sequenceNameSQL);
+ return buf.toString();
+ }
+
+ @Override
+ protected void appendSelect(SQLBuffer selectSQL, Object alias, Select sel,
+ int idx) {
+ // if this is a literal value, add a cast...
+ Object val = sel.getSelects().get(idx);
+ boolean toCast = (val instanceof Lit) &&
+ ((Lit)val).getParseType() != Literal.TYPE_DATE &&
+ ((Lit)val).getParseType() != Literal.TYPE_TIME &&
+ ((Lit)val).getParseType() != Literal.TYPE_TIMESTAMP;
+
+ if (toCast)
+ selectSQL.append("CAST(");
+
+ // ... and add the select per super's behavior...
+ super.appendSelect(selectSQL, alias, sel, idx);
+
+ // ... and finish the cast
+ if (toCast) {
+ Class c = ((Lit) val).getType();
+ int javaTypeCode = JavaTypes.getTypeCode(c);
+ int jdbcTypeCode = getJDBCType(javaTypeCode, false);
+ String typeName = getTypeName(jdbcTypeCode);
+ selectSQL.append(" AS " + typeName);
+
+ // if the literal is a string, use the default char col size
+ // in the cast statement.
+ if (String.class.equals(c))
+ selectSQL.append("(" + characterColumnSize + ")");
+
+ selectSQL.append(")");
+ }
+ }
}
Modified: openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/localizer.properties
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/localizer.properties?rev=987013&r1=987012&r2=987013&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/localizer.properties (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/sql/localizer.properties Thu Aug 19 04:19:39 2010
@@ -220,4 +220,4 @@ sequencesql-override: Going to override
the property. This will allow openJPA to detect a difference between the DB2 default \
string and the string set in the property and will further allow openJPA to use the \
string defined by the property rather than the default string for DB2.
-
+invalid-locking-mode: Invalid locking mode for SolidDB: "{0}"
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/GroupingTestCase.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/GroupingTestCase.java?rev=987013&r1=987012&r2=987013&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/GroupingTestCase.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/query/GroupingTestCase.java Thu Aug 19 04:19:39 2010
@@ -26,6 +26,7 @@ import javax.persistence.Query;
import org.apache.openjpa.jdbc.conf.JDBCConfiguration;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.jdbc.sql.DerbyDictionary;
+import org.apache.openjpa.jdbc.sql.SolidDBDictionary;
import org.apache.openjpa.persistence.test.SingleEMTestCase;
import org.apache.openjpa.persistence.simple.AllFieldTypes;
import org.apache.openjpa.persistence.ArgumentException;
@@ -186,6 +187,10 @@ public abstract class GroupingTestCase
}
public void testSubstringInGroupBy() {
+ DBDictionary dict = ((JDBCConfiguration)emf.getConfiguration()).getDBDictionaryInstance();
+ if (dict instanceof SolidDBDictionary)
+ return;
+
// this is an extension of JPQL
Query q = em.createQuery("select substring(o.stringField, 1, 1), " +
"count(o) from AllFieldTypes o " +