changes for JIRA OPENJPA-182

git-svn-id: https://svn.apache.org/repos/asf/incubator/openjpa/trunk@525252 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
David J. Wisneski 2007-04-03 19:34:59 +00:00
parent 9c25f9bdf5
commit 9e8e265d6c
2 changed files with 239 additions and 6 deletions

View File

@ -52,7 +52,7 @@ public abstract class AbstractDB2Dictionary
supportsLockingWithOrderClause = false;
supportsLockingWithOuterJoin = false;
supportsLockingWithInnerJoin = false;
supportsLockingWithSelectRange = false;
supportsLockingWithSelectRange = true;
requiresAutoCommitForMetaData = true;
requiresAliasForSubselect = true;

View File

@ -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 class DB2Dictionary
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 "
@ -171,6 +184,18 @@ public class DB2Dictionary
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;
supportsLockingWithInnerJoin = true;
@ -198,9 +223,217 @@ public class DB2Dictionary
}
}
/** 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())).