mirror of https://github.com/apache/openjpa.git
Resolving JIRA report OPENJPA-63 for better pessimistic lock support for DB2. Instead of the usual "for update" clause, db2 dictionary will now use "with rr use and keep update locks" clause.
A couple of additional changes were necessary to properly detect the version of DB2 currently in use. git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@482189 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
ca45e3292a
commit
970f647622
File diff suppressed because it is too large
Load Diff
|
@ -1,144 +1,162 @@
|
||||||
/*
|
/*
|
||||||
* Copyright 2006 The Apache Software Foundation.
|
* Copyright 2006 The Apache Software Foundation.
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
* you may not use this file except in compliance with the License.
|
* you may not use this file except in compliance with the License.
|
||||||
* You may obtain a copy of the License at
|
* You may obtain a copy of the License at
|
||||||
*
|
*
|
||||||
* http://www.apache.org/licenses/LICENSE-2.0
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
*
|
*
|
||||||
* Unless required by applicable law or agreed to in writing, software
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
* See the License for the specific language governing permissions and
|
* See the License for the specific language governing permissions and
|
||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
package org.apache.openjpa.jdbc.sql;
|
package org.apache.openjpa.jdbc.sql;
|
||||||
|
|
||||||
import java.sql.Connection;
|
import java.sql.Connection;
|
||||||
import java.sql.SQLException;
|
import java.sql.DatabaseMetaData;
|
||||||
import java.util.Arrays;
|
import java.sql.SQLException;
|
||||||
|
import java.util.Arrays;
|
||||||
import org.apache.openjpa.jdbc.schema.Sequence;
|
|
||||||
|
import org.apache.openjpa.jdbc.schema.Sequence;
|
||||||
/**
|
|
||||||
* Dictionary for IBM DB2 database.
|
/**
|
||||||
*/
|
* Dictionary for IBM DB2 database.
|
||||||
public class DB2Dictionary
|
*/
|
||||||
extends AbstractDB2Dictionary {
|
public class DB2Dictionary
|
||||||
|
extends AbstractDB2Dictionary {
|
||||||
public DB2Dictionary() {
|
|
||||||
platform = "DB2";
|
public DB2Dictionary() {
|
||||||
validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
|
platform = "DB2";
|
||||||
+ "SYSIBM.SYSTABLES";
|
validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
|
||||||
supportsSelectEndIndex = true;
|
+ "SYSIBM.SYSTABLES";
|
||||||
|
supportsSelectEndIndex = true;
|
||||||
nextSequenceQuery = "VALUES NEXTVAL FOR {0}";
|
|
||||||
|
nextSequenceQuery = "VALUES NEXTVAL FOR {0}";
|
||||||
binaryTypeName = "BLOB(1M)";
|
|
||||||
longVarbinaryTypeName = "BLOB(1M)";
|
binaryTypeName = "BLOB(1M)";
|
||||||
varbinaryTypeName = "BLOB(1M)";
|
longVarbinaryTypeName = "BLOB(1M)";
|
||||||
clobTypeName = "CLOB(1M)";
|
varbinaryTypeName = "BLOB(1M)";
|
||||||
longVarcharTypeName = "LONG VARCHAR";
|
clobTypeName = "CLOB(1M)";
|
||||||
|
longVarcharTypeName = "LONG VARCHAR";
|
||||||
fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
|
|
||||||
"LONG VARCHAR FOR BIT DATA", "LONG VARCHAR", "LONG VARGRAPHIC",
|
fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
|
||||||
}));
|
"LONG VARCHAR FOR BIT DATA", "LONG VARCHAR", "LONG VARGRAPHIC",
|
||||||
|
}));
|
||||||
maxConstraintNameLength = 18;
|
|
||||||
maxIndexNameLength = 18;
|
maxConstraintNameLength = 18;
|
||||||
maxColumnNameLength = 30;
|
maxIndexNameLength = 18;
|
||||||
supportsDeferredConstraints = false;
|
maxColumnNameLength = 30;
|
||||||
supportsDefaultDeleteAction = false;
|
supportsDeferredConstraints = false;
|
||||||
supportsAlterTableWithDropColumn = false;
|
supportsDefaultDeleteAction = false;
|
||||||
|
supportsAlterTableWithDropColumn = false;
|
||||||
supportsNullTableForGetColumns = false;
|
|
||||||
|
supportsNullTableForGetColumns = false;
|
||||||
reservedWordSet.addAll(Arrays.asList(new String[]{
|
|
||||||
"AFTER", "ALIAS", "ALLOW", "APPLICATION", "ASSOCIATE", "ASUTIME",
|
reservedWordSet.addAll(Arrays.asList(new String[]{
|
||||||
"AUDIT", "AUX", "AUXILIARY", "BEFORE", "BINARY", "BUFFERPOOL",
|
"AFTER", "ALIAS", "ALLOW", "APPLICATION", "ASSOCIATE", "ASUTIME",
|
||||||
"CACHE", "CALL", "CALLED", "CAPTURE", "CARDINALITY", "CCSID",
|
"AUDIT", "AUX", "AUXILIARY", "BEFORE", "BINARY", "BUFFERPOOL",
|
||||||
"CLUSTER", "COLLECTION", "COLLID", "COMMENT", "CONCAT",
|
"CACHE", "CALL", "CALLED", "CAPTURE", "CARDINALITY", "CCSID",
|
||||||
"CONDITION", "CONTAINS", "COUNT_BIG", "CURRENT_LC_CTYPE",
|
"CLUSTER", "COLLECTION", "COLLID", "COMMENT", "CONCAT",
|
||||||
"CURRENT_PATH", "CURRENT_SERVER", "CURRENT_TIMEZONE", "CYCLE",
|
"CONDITION", "CONTAINS", "COUNT_BIG", "CURRENT_LC_CTYPE",
|
||||||
"DATA", "DATABASE", "DAYS", "DB2GENERAL", "DB2GENRL", "DB2SQL",
|
"CURRENT_PATH", "CURRENT_SERVER", "CURRENT_TIMEZONE", "CYCLE",
|
||||||
"DBINFO", "DEFAULTS", "DEFINITION", "DETERMINISTIC", "DISALLOW",
|
"DATA", "DATABASE", "DAYS", "DB2GENERAL", "DB2GENRL", "DB2SQL",
|
||||||
"DO", "DSNHATTR", "DSSIZE", "DYNAMIC", "EACH", "EDITPROC", "ELSEIF",
|
"DBINFO", "DEFAULTS", "DEFINITION", "DETERMINISTIC", "DISALLOW",
|
||||||
"ENCODING", "END-EXEC1", "ERASE", "EXCLUDING", "EXIT", "FENCED",
|
"DO", "DSNHATTR", "DSSIZE", "DYNAMIC", "EACH", "EDITPROC", "ELSEIF",
|
||||||
"FIELDPROC", "FILE", "FINAL", "FREE", "FUNCTION", "GENERAL",
|
"ENCODING", "END-EXEC1", "ERASE", "EXCLUDING", "EXIT", "FENCED",
|
||||||
"GENERATED", "GRAPHIC", "HANDLER", "HOLD", "HOURS", "IF",
|
"FIELDPROC", "FILE", "FINAL", "FREE", "FUNCTION", "GENERAL",
|
||||||
"INCLUDING", "INCREMENT", "INDEX", "INHERIT", "INOUT", "INTEGRITY",
|
"GENERATED", "GRAPHIC", "HANDLER", "HOLD", "HOURS", "IF",
|
||||||
"ISOBID", "ITERATE", "JAR", "JAVA", "LABEL", "LC_CTYPE", "LEAVE",
|
"INCLUDING", "INCREMENT", "INDEX", "INHERIT", "INOUT", "INTEGRITY",
|
||||||
"LINKTYPE", "LOCALE", "LOCATOR", "LOCATORS", "LOCK", "LOCKMAX",
|
"ISOBID", "ITERATE", "JAR", "JAVA", "LABEL", "LC_CTYPE", "LEAVE",
|
||||||
"LOCKSIZE", "LONG", "LOOP", "MAXVALUE", "MICROSECOND",
|
"LINKTYPE", "LOCALE", "LOCATOR", "LOCATORS", "LOCK", "LOCKMAX",
|
||||||
"MICROSECONDS", "MINUTES", "MINVALUE", "MODE", "MODIFIES", "MONTHS",
|
"LOCKSIZE", "LONG", "LOOP", "MAXVALUE", "MICROSECOND",
|
||||||
"NEW", "NEW_TABLE", "NOCACHE", "NOCYCLE", "NODENAME", "NODENUMBER",
|
"MICROSECONDS", "MINUTES", "MINVALUE", "MODE", "MODIFIES", "MONTHS",
|
||||||
"NOMAXVALUE", "NOMINVALUE", "NOORDER", "NULLS", "NUMPARTS", "OBID",
|
"NEW", "NEW_TABLE", "NOCACHE", "NOCYCLE", "NODENAME", "NODENUMBER",
|
||||||
"OLD", "OLD_TABLE", "OPTIMIZATION", "OPTIMIZE", "OUT", "OVERRIDING",
|
"NOMAXVALUE", "NOMINVALUE", "NOORDER", "NULLS", "NUMPARTS", "OBID",
|
||||||
"PACKAGE", "PARAMETER", "PART", "PARTITION", "PATH", "PIECESIZE",
|
"OLD", "OLD_TABLE", "OPTIMIZATION", "OPTIMIZE", "OUT", "OVERRIDING",
|
||||||
"PLAN", "PRIQTY", "PROGRAM", "PSID", "QUERYNO", "READS", "RECOVERY",
|
"PACKAGE", "PARAMETER", "PART", "PARTITION", "PATH", "PIECESIZE",
|
||||||
"REFERENCING", "RELEASE", "RENAME", "REPEAT", "RESET", "RESIGNAL",
|
"PLAN", "PRIQTY", "PROGRAM", "PSID", "QUERYNO", "READS", "RECOVERY",
|
||||||
"RESTART", "RESULT", "RESULT_SET_LOCATOR", "RETURN", "RETURNS",
|
"REFERENCING", "RELEASE", "RENAME", "REPEAT", "RESET", "RESIGNAL",
|
||||||
"ROUTINE", "ROW", "RRN", "RUN", "SAVEPOINT", "SCRATCHPAD",
|
"RESTART", "RESULT", "RESULT_SET_LOCATOR", "RETURN", "RETURNS",
|
||||||
"SECONDS", "SECQTY", "SECURITY", "SENSITIVE", "SIGNAL", "SIMPLE",
|
"ROUTINE", "ROW", "RRN", "RUN", "SAVEPOINT", "SCRATCHPAD",
|
||||||
"SOURCE", "SPECIFIC", "SQLID", "STANDARD", "START", "STATIC",
|
"SECONDS", "SECQTY", "SECURITY", "SENSITIVE", "SIGNAL", "SIMPLE",
|
||||||
"STAY", "STOGROUP", "STORES", "STYLE", "SUBPAGES", "SYNONYM",
|
"SOURCE", "SPECIFIC", "SQLID", "STANDARD", "START", "STATIC",
|
||||||
"SYSFUN", "SYSIBM", "SYSPROC", "SYSTEM", "TABLESPACE", "TRIGGER",
|
"STAY", "STOGROUP", "STORES", "STYLE", "SUBPAGES", "SYNONYM",
|
||||||
"TYPE", "UNDO", "UNTIL", "VALIDPROC", "VARIABLE", "VARIANT", "VCAT",
|
"SYSFUN", "SYSIBM", "SYSPROC", "SYSTEM", "TABLESPACE", "TRIGGER",
|
||||||
"VOLUMES", "WHILE", "WLM", "YEARS",
|
"TYPE", "UNDO", "UNTIL", "VALIDPROC", "VARIABLE", "VARIANT", "VCAT",
|
||||||
}));
|
"VOLUMES", "WHILE", "WLM", "YEARS",
|
||||||
}
|
}));
|
||||||
|
}
|
||||||
public boolean supportsRandomAccessResultSet(Select sel,
|
|
||||||
boolean forUpdate) {
|
public boolean supportsRandomAccessResultSet(Select sel,
|
||||||
return !forUpdate
|
boolean forUpdate) {
|
||||||
&& super.supportsRandomAccessResultSet(sel, forUpdate);
|
return !forUpdate
|
||||||
}
|
&& super.supportsRandomAccessResultSet(sel, forUpdate);
|
||||||
|
}
|
||||||
protected void appendSelectRange(SQLBuffer buf, long start, long end) {
|
|
||||||
// appends the literal range string, since DB2 is unable to handle
|
protected void appendSelectRange(SQLBuffer buf, long start, long end) {
|
||||||
// a bound parameter for it
|
// appends the literal range string, since DB2 is unable to handle
|
||||||
buf.append(" FETCH FIRST ").append(Long.toString(end)).
|
// a bound parameter for it
|
||||||
append(" ROWS ONLY");
|
buf.append(" FETCH FIRST ").append(Long.toString(end)).
|
||||||
}
|
append(" ROWS ONLY");
|
||||||
|
}
|
||||||
public String[] getCreateSequenceSQL(Sequence seq) {
|
|
||||||
String[] sql = super.getCreateSequenceSQL(seq);
|
public String[] getCreateSequenceSQL(Sequence seq) {
|
||||||
if (seq.getAllocate() > 1)
|
String[] sql = super.getCreateSequenceSQL(seq);
|
||||||
sql[0] += " CACHE " + seq.getAllocate();
|
if (seq.getAllocate() > 1)
|
||||||
return sql;
|
sql[0] += " CACHE " + seq.getAllocate();
|
||||||
}
|
return sql;
|
||||||
|
}
|
||||||
protected String getSequencesSQL(String schemaName, String sequenceName) {
|
|
||||||
StringBuffer buf = new StringBuffer();
|
protected String getSequencesSQL(String schemaName, String sequenceName) {
|
||||||
buf.append("SELECT SEQSCHEMA AS SEQUENCE_SCHEMA, ").
|
StringBuffer buf = new StringBuffer();
|
||||||
append("SEQNAME AS SEQUENCE_NAME FROM SYSCAT.SEQUENCES");
|
buf.append("SELECT SEQSCHEMA AS SEQUENCE_SCHEMA, ").
|
||||||
if (schemaName != null || sequenceName != null)
|
append("SEQNAME AS SEQUENCE_NAME FROM SYSCAT.SEQUENCES");
|
||||||
buf.append(" WHERE ");
|
if (schemaName != null || sequenceName != null)
|
||||||
if (schemaName != null) {
|
buf.append(" WHERE ");
|
||||||
buf.append("SEQSCHEMA = ?");
|
if (schemaName != null) {
|
||||||
if (sequenceName != null)
|
buf.append("SEQSCHEMA = ?");
|
||||||
buf.append(" AND ");
|
if (sequenceName != null)
|
||||||
}
|
buf.append(" AND ");
|
||||||
if (sequenceName != null)
|
}
|
||||||
buf.append("SEQNAME = ?");
|
if (sequenceName != null)
|
||||||
return buf.toString();
|
buf.append("SEQNAME = ?");
|
||||||
}
|
return buf.toString();
|
||||||
|
}
|
||||||
public Connection decorate(Connection conn)
|
|
||||||
throws SQLException {
|
public Connection decorate(Connection conn)
|
||||||
// some versions of the DB2 driver seem to default to
|
throws SQLException {
|
||||||
// READ_UNCOMMITTED, which will prevent locking from working
|
// some versions of the DB2 driver seem to default to
|
||||||
// (multiple SELECT ... FOR UPDATE statements are allowed on
|
// READ_UNCOMMITTED, which will prevent locking from working
|
||||||
// the same instance); if we have not overridden the
|
// (multiple SELECT ... FOR UPDATE statements are allowed on
|
||||||
// transaction isolation in the configuration, default to
|
// the same instance); if we have not overridden the
|
||||||
// TRANSACTION_READ_COMMITTED
|
// transaction isolation in the configuration, default to
|
||||||
conn = super.decorate(conn);
|
// TRANSACTION_READ_COMMITTED
|
||||||
|
conn = super.decorate(conn);
|
||||||
if (conf.getTransactionIsolationConstant() == -1
|
|
||||||
&& conn.getTransactionIsolation() < conn.TRANSACTION_READ_COMMITTED)
|
if (conf.getTransactionIsolationConstant() == -1
|
||||||
conn.setTransactionIsolation(conn.TRANSACTION_READ_COMMITTED);
|
&& conn.getTransactionIsolation() < conn.TRANSACTION_READ_COMMITTED)
|
||||||
|
conn.setTransactionIsolation(conn.TRANSACTION_READ_COMMITTED);
|
||||||
return conn;
|
|
||||||
}
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void connectedConfiguration(Connection conn) throws SQLException {
|
||||||
|
super.connectedConfiguration(conn);
|
||||||
|
|
||||||
|
DatabaseMetaData metaData = conn.getMetaData();
|
||||||
|
if (metaData.getJDBCMajorVersion() >= 3) {
|
||||||
|
int maj = metaData.getDatabaseMajorVersion();
|
||||||
|
int min = metaData.getDatabaseMinorVersion();
|
||||||
|
|
||||||
|
if (maj >= 9 || (maj == 8 && min >= 2)) {
|
||||||
|
supportsLockingWithMultipleTables = true;
|
||||||
|
supportsLockingWithInnerJoin = true;
|
||||||
|
supportsLockingWithOuterJoin = true;
|
||||||
|
forUpdateClause = "WITH RR USE AND KEEP UPDATE LOCKS";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue