Author: wisneskid
Date: Tue Apr 3 12:34:59 2007
New Revision: 525252
URL: http://svn.apache.org/viewvc?view=rev&rev=525252
Log:
changes for JIRA OPENJPA-182
Modified:
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
Modified:
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
URL:
http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java?view=diff&rev=525252&r1=525251&r2=525252
==============================================================================
---
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
(original)
+++
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/AbstractDB2Dictionary.java
Tue Apr 3 12:34:59 2007
@@ -52,7 +52,7 @@
supportsLockingWithOrderClause = false;
supportsLockingWithOuterJoin = false;
supportsLockingWithInnerJoin = false;
- supportsLockingWithSelectRange = false;
+ supportsLockingWithSelectRange = true;
requiresAutoCommitForMetaData = true;
requiresAliasForSubselect = true;
Modified:
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
URL:
http://svn.apache.org/viewvc/incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?view=diff&rev=525252&r1=525251&r2=525252
==============================================================================
---
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
(original)
+++
incubator/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
Tue Apr 3 12:34:59 2007
@@ -15,13 +15,15 @@
*/
package org.apache.openjpa.jdbc.sql;
+import java.lang.reflect.Method;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.Arrays;
-
+import java.util.StringTokenizer;
import org.apache.openjpa.jdbc.kernel.JDBCFetchConfiguration;
import org.apache.openjpa.jdbc.schema.Sequence;
+import org.apache.openjpa.lib.log.Log;
/**
* Dictionary for IBM DB2 database.
@@ -31,7 +33,18 @@
public String optimizeClause = "optimize for";
public String rowClause = "row";
-
+ private int db2ServerType = 0;
+ private static final int db2ISeriesV5R3AndEarlier = 1;
+ private static final int db2UDBV81OrEarlier = 2;
+ private static final int db2ZOSV8x = 3;
+ private static final int db2UDBV82AndLater = 4;
+ private static final int db2ISeriesV5R4AndLater = 5;
+ private static final String forUpdateOfClause="FOR UPDATE OF";
+ private static final String withRSClause="WITH RS";
+ private static final String withRRClause="WITH RR";
+ private static final String useKeepUpdateLockClause= "USE AND KEEP UPDATE
LOCKS";
+ private static final String useKeepExclusiveLockClause="USE AND KEEP
EXCLUSIVE LOCKS";
+ private static final String forReadOnlyClause = "FOR READ ONLY";
public DB2Dictionary() {
platform = "DB2";
validationSQL = "SELECT DISTINCT(CURRENT TIMESTAMP) FROM "
@@ -170,6 +183,18 @@
if (isJDBC3(metaData)) {
int maj = metaData.getDatabaseMajorVersion();
int min = metaData.getDatabaseMinorVersion();
+
+ // Determine the type of DB2 database
+ if (isDB2ISeriesV5R3AndEarlier(metaData))
+ db2ServerType =db2ISeriesV5R3AndEarlier;
+ else if (isDB2UDBV81OrEarlier(metaData,maj,min))
+ db2ServerType =db2UDBV81OrEarlier;
+ else if (isDB2ZOSV8x(metaData,maj))
+ db2ServerType =db2ZOSV8x;
+ else if (isDB2UDBV82AndLater(metaData,maj,min))
+ db2ServerType=db2UDBV82AndLater;
+ else if (isDB2ISeriesV5R4AndLater(metaData))
+ db2ServerType=db2ISeriesV5R4AndLater;
if (maj >= 9 || (maj == 8 && min >= 2)) {
supportsLockingWithMultipleTables = true;
@@ -198,13 +223,221 @@
}
}
+ /** Get the update clause for the query based on the
+ * updateClause and isolationLevel hints
+ */
+ public String getForUpdateClause(JDBCFetchConfiguration fetch, boolean
forUpdate) {
+ String isolationLevel = null;
+ Boolean updateClause = null;
+ DatabaseMetaData metaData = null;
+ StringBuffer forUpdateString = new StringBuffer();
+ try {
+ // Determine the update clause/isolationLevel the hint
+ // overrides the persistence.xml value
+ if (fetch != null && fetch.getHint("openjpa.hint.updateClause")
+ !=null )
+ updateClause = (Boolean)fetch.
+ getHint("openjpa.hint.updateClause");
+ else
+ updateClause = forUpdate;
+ if (fetch != null &&fetch.getHint("openjpa.hint.isolationLevel")
+ !=null )
+ isolationLevel = (String)fetch.
+ getHint("openjpa.hint.isolationLevel");
+ else
+ isolationLevel = conf.getTransactionIsolation();
+ if (updateClause == false)
+ //This sql is not for update so add FOR Read Only clause
+ forUpdateString.append(" ").append(forReadOnlyClause)
+ .append(" ");
+ else if (updateClause == true){
+
+ switch(db2ServerType){
+ case db2ISeriesV5R3AndEarlier:
+ case db2UDBV81OrEarlier:
+ if (isolationLevel.equals("read-uncommitted"))
+ forUpdateString.append(" ").append(withRSClause)
+ .append(" ").append(forUpdateOfClause).append(" ");
+ else
+ forUpdateString.append(" ").append(forUpdateOfClause)
+ .append(" ");
+ break;
+ case db2ZOSV8x:
+ case db2UDBV82AndLater:
+ if (isolationLevel.equals("serializable"))
+ forUpdateString.append(" ").append(withRRClause)
+ .append(" ").append(useKeepUpdateLockClause)
+ .append(" ");
+ else
+ forUpdateString.append(" ").append(withRSClause)
+ .append(" ").append(useKeepUpdateLockClause)
+ .append(" ");
+ break;
+ case db2ISeriesV5R4AndLater:
+ if (isolationLevel.equals("serializable"))
+ forUpdateString.append(" ").append(withRRClause)
+ .append(" ").append(useKeepExclusiveLockClause)
+ .append(" ");
+ else
+ forUpdateString.append(" ").append(withRSClause)
+ .append(" ").append(useKeepExclusiveLockClause)
+ .append(" ");
+ }
+ }
+ }
+ catch (Exception e) {
+ if (log.isTraceEnabled())
+ log.error(e.toString(),e);
+ }
+ return forUpdateString.toString();
+ }
+
+
+ /** Override the DBDictionary toSelect to call getOptimizeClause and
append
+ * to the select string
+ */
+ public SQLBuffer toSelect(SQLBuffer selects, JDBCFetchConfiguration fetch,
+ SQLBuffer from, SQLBuffer where, SQLBuffer group,
+ SQLBuffer having, SQLBuffer order,
+ boolean distinct, boolean forUpdate, long start, long end,
+ int expectedResultCount) {
+ String forUpdateString = getForUpdateClause(fetch,forUpdate);
+ SQLBuffer selString = toOperation(getSelectOperation(fetch),
+ selects, from, where,
+ group, having, order, distinct,
+ forUpdate, start, end,forUpdateString);
+ return selString;
+ }
+
+ public boolean isDB2UDBV82AndLater(DatabaseMetaData metadata, int maj,
+ int min) throws SQLException {
+ boolean match = false;
+ if (metadata.getDatabaseProductVersion().indexOf("SQL") != -1
+ && ((maj ==8 && min >=2) ||(maj >=8)))
+ match = true;
+ return match;
+ }
+
+ public boolean isDB2ZOSV8x(DatabaseMetaData metadata,int maj)
+ throws SQLException {
+ boolean match = false;
+ if (metadata.getDatabaseProductVersion().indexOf("DSN") != -1
+ && maj ==8 )
+ match = true;
+ return match;
+ }
+
+ public boolean isDB2ISeriesV5R3AndEarlier(DatabaseMetaData metadata)
+ throws SQLException {
+ boolean match = false;
+ if (metadata.getDatabaseProductVersion().indexOf("AS") != -1
+ && generateVersionNumber(metadata.getDatabaseProductVersion())
+ <= 530 )
+ match = true;
+ return match;
+ }
+
+ public boolean isDB2ISeriesV5R4AndLater(DatabaseMetaData metadata)
+ throws SQLException {
+ boolean match = false;
+ if (metadata.getDatabaseProductVersion().indexOf("AS") != -1
+ && generateVersionNumber(metadata.getDatabaseProductVersion())
+ >= 540 )
+ match = true;
+ return match;
+ }
+
+ public boolean isDB2UDBV81OrEarlier(DatabaseMetaData metadata,int maj,
+ int min) throws SQLException {
+ boolean match = false;
+ if (metadata.getDatabaseProductVersion().indexOf("SQL") != -1 &&
+ ((maj ==8 && min <=1)|| maj <8 ))
+ match = true;
+ return match;
+ }
+
+ /** Get the version number for the ISeries
+ */
+ protected int generateVersionNumber(String versionString) {
+ String s = versionString.substring(versionString.indexOf('V'));
+ s = s.toUpperCase();
+ int i = -1;
+ StringTokenizer stringtokenizer = new StringTokenizer(s, "VRM", false);
+ if (stringtokenizer.countTokens() == 3)
+ {
+ String s1 = stringtokenizer.nextToken();
+ s1 = s1 + stringtokenizer.nextToken();
+ s1 = s1 + stringtokenizer.nextToken();
+ i = Integer.parseInt(s1);
+ }
+ return i;
+ }
+
+
+ /**
+ * Override the toOperationMethod of DBDictionary to pass the
+ * forUpdateString.
+ */
+ protected SQLBuffer toOperation(String op, SQLBuffer selects,
+ SQLBuffer from, SQLBuffer where, SQLBuffer group, SQLBuffer having,
+ SQLBuffer order, boolean distinct, boolean forUpdate, long start,
+ long end,String forUpdateString) {
+ SQLBuffer buf = new SQLBuffer(this);
+ buf.append(op);
+ boolean range = start != 0 || end != Long.MAX_VALUE;
+ if (range && rangePosition == RANGE_PRE_DISTINCT)
+ appendSelectRange(buf, start, end);
+ if (distinct)
+ buf.append(" DISTINCT");
+ if (range && rangePosition == RANGE_POST_DISTINCT)
+ appendSelectRange(buf, start, end);
+ buf.append(" ").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()) {
+ assertSupport(supportsHaving, "SupportsHaving");
+ buf.append(" HAVING ").append(having);
+ }
+ if (order != null && !order.isEmpty())
+ buf.append(" ORDER BY ").append(order);
+ if (range && rangePosition == RANGE_POST_SELECT)
+ appendSelectRange(buf, start, end);
+
+ if (!simulateLocking ) {
+ assertSupport(supportsSelectForUpdate, "SupportsSelectForUpdate");
+ buf.append(" ").append(forUpdateString);
+ }
+ if (range && rangePosition == RANGE_POST_LOCK)
+ appendSelectRange(buf, start, end);
+ return buf;
+ }
+
public SQLBuffer toSelect(Select sel, boolean forUpdate,
JDBCFetchConfiguration fetch) {
- SQLBuffer buf = super.toSelect(sel, forUpdate, fetch);
+ sel.addJoinClassConditions();
+ boolean update = forUpdate && sel.getFromSelect() == null;
+ SQLBuffer select = getSelects(sel, false, update);
+ SQLBuffer ordering = null;
+ if (!sel.isAggregate() || sel.getGrouping() != null)
+ ordering = sel.getOrdering();
+ SQLBuffer from;
+ if (sel.getFromSelect() != null)
+ from = getFromSelect(sel, forUpdate);
+ else
+ from = getFrom(sel, update);
+ SQLBuffer where = getWhere(sel, update);
+ String forUpdateString = getForUpdateClause(fetch,forUpdate);
+ SQLBuffer buf = toOperation(getSelectOperation(fetch), select,
+ from, where,sel.getGrouping(), sel.getHaving(), ordering,
+ sel.isDistinct(), forUpdate, sel.getStartIndex(),
+ sel.getEndIndex(),forUpdateString);
if (sel.getExpectedResultCount() > 0)
buf.append(" ").append(optimizeClause).append(" ").
- append(String.valueOf(sel.getExpectedResultCount())).
- append(" ").append(rowClause);
+ append(String.valueOf(sel.getExpectedResultCount())).
+ append(" ").append(rowClause);
return buf;
}
}