mirror of https://github.com/apache/openjpa.git
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:
parent
9c25f9bdf5
commit
9e8e265d6c
|
@ -52,7 +52,7 @@ public abstract class AbstractDB2Dictionary
|
|||
supportsLockingWithOrderClause = false;
|
||||
supportsLockingWithOuterJoin = false;
|
||||
supportsLockingWithInnerJoin = false;
|
||||
supportsLockingWithSelectRange = false;
|
||||
supportsLockingWithSelectRange = true;
|
||||
|
||||
requiresAutoCommitForMetaData = true;
|
||||
requiresAliasForSubselect = true;
|
||||
|
|
|
@ -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 "
|
||||
|
@ -170,6 +183,18 @@ public class DB2Dictionary
|
|||
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 @@ 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())).
|
||||
append(" ").append(rowClause);
|
||||
append(String.valueOf(sel.getExpectedResultCount())).
|
||||
append(" ").append(rowClause);
|
||||
return buf;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue