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 2007/09/11 07:32:38 UTC
svn commit: r574464 - in /openjpa/trunk:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/
Author: fancy
Date: Mon Sep 10 22:32:37 2007
New Revision: 574464
URL: http://svn.apache.org/viewvc?rev=574464&view=rev
Log:
OPENJPA-360 SQL FOR UPDATE OF incorrectly generated for DB2 UDB version8.1 or earlier and DB2 ISeries V5R3 or earlier.
These DB2 version also require the "optimize for <n> row" clause appear before FOR UPDATE clause.
Due to this requirement, the OPTIMIZE clause will appear before FOR UPDATE clause for all DB2 versions.
Also fixed the affected testcases.
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DBDictionary.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestIsolationLevelOverride.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestOptimizeForClause.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestSelectForUpdateOverride.java
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java?rev=574464&r1=574463&r2=574464&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java Mon Sep 10 22:32:37 2007
@@ -50,12 +50,12 @@
public String optimizeClause = "optimize for";
public String rowClause = "row";
protected int db2ServerType = 0;
- protected static final int db2ISeriesV5R3OrEarlier = 1;
- protected static final int db2UDBV81OrEarlier = 2;
- protected static final int db2ZOSV8xOrLater = 3;
- protected static final int db2UDBV82OrLater = 4;
- protected static final int db2ISeriesV5R4OrLater = 5;
- private static final String forUpdateOfClause = "FOR UPDATE OF";
+ public static final int db2ISeriesV5R3OrEarlier = 1;
+ public static final int db2UDBV81OrEarlier = 2;
+ public static final int db2ZOSV8xOrLater = 3;
+ public static final int db2UDBV82OrLater = 4;
+ public static final int db2ISeriesV5R4OrLater = 5;
+ private static final String forUpdate = "FOR UPDATE";
private static final String withRSClause = "WITH RS";
private static final String withRRClause = "WITH RR";
private static final String useKeepUpdateLockClause
@@ -313,9 +313,12 @@
* updateClause and isolationLevel hints
*/
protected String getForUpdateClause(JDBCFetchConfiguration fetch,
- boolean forUpdate) {
+ boolean isForUpdate) {
int isolationLevel;
- StringBuffer forUpdateString = new StringBuffer();
+ // For db2UDBV81OrEarlier and db2ISeriesV5R3OrEarlier:
+ // "optimize for" clause appears before "for update" clause.
+ StringBuffer forUpdateString = new StringBuffer(
+ getOptimizeClause(fetch));
try {
// Determine the isolationLevel; the fetch
// configuration data overrides the persistence.xml value
@@ -324,16 +327,15 @@
else
isolationLevel = conf.getTransactionIsolationConstant();
- if (forUpdate) {
+ if (isForUpdate) {
switch(db2ServerType) {
case db2ISeriesV5R3OrEarlier:
case db2UDBV81OrEarlier:
- if (isolationLevel ==
- Connection.TRANSACTION_READ_UNCOMMITTED) {
- forUpdateString.append(" ").append(withRSClause)
- .append(" ").append(forUpdateOfClause);
- } else
- forUpdateString.append(" ").append(forUpdateOfClause);
+ if (isolationLevel == Connection.TRANSACTION_SERIALIZABLE)
+ forUpdateString.append(" ").append(forUpdateClause);
+ else
+ forUpdateString.append(" ").append(forUpdate)
+ .append(" ").append(withRSClause);
break;
case db2ZOSV8xOrLater:
case db2UDBV82OrLater:
@@ -368,7 +370,7 @@
return forUpdateString.toString();
}
- public boolean isDB2UDBV82OrLater() throws SQLException {
+ public boolean isDB2UDBV82OrLater() {
boolean match = false;
if ((databaseProductVersion.indexOf("SQL") != -1
|| databaseProductName.indexOf("DB2/") != -1)
@@ -377,8 +379,7 @@
return match;
}
- public boolean isDB2ZOSV8xOrLater()
- throws SQLException {
+ public boolean isDB2ZOSV8xOrLater() {
boolean match = false;
if ((databaseProductVersion.indexOf("DSN") != -1
|| databaseProductName.indexOf("DB2/") == -1)
@@ -387,8 +388,7 @@
return match;
}
- public boolean isDB2ISeriesV5R3OrEarlier()
- throws SQLException {
+ public boolean isDB2ISeriesV5R3OrEarlier() {
boolean match = false;
if (databaseProductName.indexOf("AS") != -1
&& ((maj == 5 && min <=3) || maj < 5))
@@ -396,8 +396,7 @@
return match;
}
- public boolean isDB2ISeriesV5R4OrLater()
- throws SQLException {
+ public boolean isDB2ISeriesV5R4OrLater() {
boolean match = false;
if (databaseProductName.indexOf("AS") != -1
&& (maj >=6 || (maj == 5 && min >=4)))
@@ -405,7 +404,7 @@
return match;
}
- public boolean isDB2UDBV81OrEarlier() throws SQLException {
+ public boolean isDB2UDBV81OrEarlier() {
boolean match = false;
if ((databaseProductVersion.indexOf("SQL") != -1
|| databaseProductName.indexOf("DB2/") != -1) &&
@@ -465,17 +464,16 @@
}
}
- public SQLBuffer toSelect(Select sel, boolean forUpdate,
- JDBCFetchConfiguration fetch) {
- SQLBuffer buf = super.toSelect(sel, forUpdate, fetch);
-
- if (sel.getExpectedResultCount() > 0) {
+ protected String getOptimizeClause(JDBCFetchConfiguration fetch) {
+ if (sel != null && sel.getExpectedResultCount() > 0) {
+ StringBuffer buf = new StringBuffer();
buf.append(" ").append(optimizeClause).append(" ")
.append(String.valueOf(sel.getExpectedResultCount()))
.append(" ").append(rowClause);
+ return buf.toString();
}
- return buf;
+ return "";
}
public OpenJPAException newStoreException(String msg, SQLException[] causes,
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=574464&r1=574463&r2=574464&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 Mon Sep 10 22:32:37 2007
@@ -325,6 +325,7 @@
private Method _setBytes = null;
private Method _setString = null;
private Method _setCharStream = null;
+ protected transient Select sel = null;
public DBDictionary() {
fixedSizeTypeNameSet.addAll(Arrays.asList(new String[]{
@@ -1988,6 +1989,7 @@
*/
public SQLBuffer toSelect(Select sel, boolean forUpdate,
JDBCFetchConfiguration fetch) {
+ this.sel = sel;
sel.addJoinClassConditions();
boolean update = forUpdate && sel.getFromSelect() == null;
SQLBuffer select = getSelects(sel, false, update);
@@ -2198,11 +2200,11 @@
* updateClause and isolationLevel hints
*/
protected String getForUpdateClause(JDBCFetchConfiguration fetch,
- boolean forUpdate) {
+ boolean isForUpdate) {
if (fetch != null && fetch.getIsolation() != -1) {
throw new InvalidStateException(_loc.get(
"isolation-level-config-not-supported", getClass().getName()));
- } else if (forUpdate && !simulateLocking) {
+ } else if (isForUpdate && !simulateLocking) {
assertSupport(supportsSelectForUpdate, "SupportsSelectForUpdate");
return forUpdateClause;
} else {
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestIsolationLevelOverride.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestIsolationLevelOverride.java?rev=574464&r1=574463&r2=574464&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestIsolationLevelOverride.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestIsolationLevelOverride.java Mon Sep 10 22:32:37 2007
@@ -81,37 +81,23 @@
q.getResultList();
if (dict instanceof DB2Dictionary) {
- if ((((DB2Dictionary) dict).getDb2ServerType() == 1)
- || (((DB2Dictionary) dict).getDb2ServerType()== 2)) {
+ int db2server = ((DB2Dictionary) dict).getDb2ServerType();
+ if (db2server == DB2Dictionary.db2ISeriesV5R3OrEarlier
+ || db2server == DB2Dictionary.db2UDBV81OrEarlier) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.id, t0.booleanField, t0.byteField,"
- + " t0.charField, t0.dateField, t0.doubleField,"
- + " t0.floatField, t0.intField, t0.longField, "
- + "t0.shortField, t0.stringField FROM "
- + "AllFieldTypes t0 WHERE \\(t0.intField = \\?\\) "
- + " FOR UPDATE OF");
+ assertContainsSQL(" FOR UPDATE");
}
// it is DB2 v82 or later
- else if ((((DB2Dictionary) dict).getDb2ServerType() == 3)
- || (((DB2Dictionary) dict).getDb2ServerType() == 4)) {
+ else if (db2server == DB2Dictionary.db2ZOSV8xOrLater
+ || db2server == DB2Dictionary.db2UDBV82OrLater) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.id, t0.booleanField, t0.byteField,"
- + " t0.charField, t0.dateField, t0.doubleField,"
- + " t0.floatField, t0.intField, t0.longField, "
- + "t0.shortField, t0.stringField FROM "
- + "AllFieldTypes t0 WHERE \\(t0.intField = \\?\\) "
- + " FOR READ ONLY WITH RR USE AND KEEP "
+ assertContainsSQL(" FOR READ ONLY WITH RR USE AND KEEP "
+ "UPDATE LOCKS");
}
- else if (((DB2Dictionary) dict).getDb2ServerType() == 5) {
+ else if (db2server == DB2Dictionary.db2ISeriesV5R4OrLater) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.id, t0.booleanField, t0.byteField,"
- + " t0.charField, t0.dateField, t0.doubleField,"
- + " t0.floatField, t0.intField, t0.longField, "
- + "t0.shortField, t0.stringField FROM "
- + "AllFieldTypes t0 WHERE \\(t0.intField = \\?\\) "
- + " FOR READ ONLY WITH RR USE AND KEEP EXCLUSIVE "
- + "LOCKS");
+ assertContainsSQL(" FOR READ ONLY WITH RR USE AND KEEP"
+ + " EXCLUSIVE LOCKS");
}
else {
fail("OpenJPA currently only supports "
@@ -124,37 +110,25 @@
.setIsolation(IsolationLevel.SERIALIZABLE);
em.find(AllFieldTypes.class, 0);
if (dict instanceof DB2Dictionary ) {
- if ((((DB2Dictionary) dict).getDb2ServerType() == 1)
- || (((DB2Dictionary) dict).getDb2ServerType()== 2)) {
+ int db2server = ((DB2Dictionary) dict).getDb2ServerType();
+ if (db2server == DB2Dictionary.db2ISeriesV5R3OrEarlier
+ || db2server == DB2Dictionary.db2UDBV81OrEarlier) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.booleanField, t0.byteField, "
- + "t0.charField, t0.dateField, t0.doubleField,"
- + " t0.floatField, t0.intField, t0.longField,"
- + " t0.shortField, t0.stringField FROM "
- + "AllFieldTypes t0 WHERE t0.id = \\? "
- + " FOR UPDATE OF optimize for 1 row");
+ assertContainsSQL(" optimize for 1 row FOR UPDATE");
}
// it is DB2 v82 or later
- else if ((((DB2Dictionary) dict).getDb2ServerType() == 3)
- || (((DB2Dictionary) dict).getDb2ServerType() == 4)) {
+ else if (db2server == DB2Dictionary.db2ZOSV8xOrLater
+ || db2server == DB2Dictionary.db2UDBV82OrLater) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.booleanField, t0.byteField, "
- + "t0.charField, t0.dateField, t0.doubleField,"
- + " t0.floatField, t0.intField, t0.longField,"
- + " t0.shortField, t0.stringField FROM "
- + "AllFieldTypes t0 WHERE t0.id = \\? "
+ assertContainsSQL(" optimize for 1 row"
+ " FOR READ ONLY WITH RR USE AND KEEP UPDATE LOCKS"
- + " optimize for 1 row");
+ );
}
- else if (((DB2Dictionary) dict).getDb2ServerType() == 5) {
+ else if (db2server == DB2Dictionary.db2ISeriesV5R4OrLater) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.booleanField, t0.byteField, "
- + "t0.charField, t0.dateField, t0.doubleField,"
- + " t0.floatField, t0.intField, t0.longField,"
- + " t0.shortField, t0.stringField FROM "
- + "AllFieldTypes t0 WHERE t0.id = \\? "
+ assertContainsSQL(" optimize for 1 row"
+ " FOR READ ONLY WITH RR USE AND KEEP EXCLUSIVE"
- + " LOCKS optimize for 1 row");
+ + " LOCKS");
}
else {
fail("OpenJPA currently only supports per-query"
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestOptimizeForClause.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestOptimizeForClause.java?rev=574464&r1=574463&r2=574464&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestOptimizeForClause.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestOptimizeForClause.java Mon Sep 10 22:32:37 2007
@@ -81,22 +81,14 @@
}
if (dict instanceof DB2Dictionary) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.id, t0.booleanField, t0.byteField," +
- " t0.charField, t0.dateField, t0.doubleField, " +
- "t0.floatField, t0.intField, t0.longField, " +
- "t0.shortField, t0.stringField FROM AllFieldTypes " +
- "t0 WHERE \\(t0.intField = \\?\\) optimize for 8 row");
+ assertContainsSQL(" optimize for 8 row");
}
}
else {
em.find(AllFieldTypes.class, 0);
if (dict instanceof DB2Dictionary ) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.booleanField, t0.byteField, " +
- "t0.charField, t0.dateField, t0.doubleField, " +
- "t0.floatField, t0.intField, t0.longField, " +
- "t0.shortField, t0.stringField FROM AllFieldTypes" +
- " t0 WHERE t0.id = \\? optimize for 1 row");
+ assertContainsSQL(" optimize for 1 row");
}
}
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestSelectForUpdateOverride.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestSelectForUpdateOverride.java?rev=574464&r1=574463&r2=574464&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestSelectForUpdateOverride.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/jdbc/TestSelectForUpdateOverride.java Mon Sep 10 22:32:37 2007
@@ -33,7 +33,14 @@
extends SQLListenerTestCase {
public void setUp() {
- setUp(AllFieldTypes.class,
+ setUp(
+// "openjpa.ConnectionDriverName",
+// "org.apache.commons.dbcp.BasicDataSource",
+
+ "openjpa.ConnectionProperties",
+ "DriverClassName=com.ibm.db2.jcc.DB2Driver,Url=jdbc:db2:demodb"
+ ,"openjpa.jdbc.SynchronizeMappings",
+ AllFieldTypes.class,
"openjpa.Optimistic", "false",
"openjpa.LockManager", "pessimistic",
"openjpa.ReadLockLevel", "none");
@@ -57,37 +64,24 @@
em.find(AllFieldTypes.class, 0);
assertEquals(1, sql.size());
if (dict instanceof DB2Dictionary) {
- if ((((DB2Dictionary) dict).getDb2ServerType() == 1)
- || (((DB2Dictionary) dict).getDb2ServerType()== 2)) {
+ int db2server = ((DB2Dictionary) dict).getDb2ServerType();
+ if (db2server == DB2Dictionary.db2ISeriesV5R3OrEarlier
+ || db2server == DB2Dictionary.db2UDBV81OrEarlier) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.booleanField, t0.byteField, "
- + "t0.charField, t0.dateField, t0.doubleField,"
- + " t0.floatField, t0.intField, t0.longField,"
- + " t0.shortField, t0.stringField FROM "
- + "AllFieldTypes t0 WHERE t0.id = \\? "
- + " FOR UPDATE OF optimize for 1 row");
+ assertContainsSQL(" optimize for 1 row FOR UPDATE");
}
// it is DB2 v82 or later
- else if ((((DB2Dictionary) dict).getDb2ServerType() == 3)
- || (((DB2Dictionary) dict).getDb2ServerType() == 4)) {
+ else if (db2server == DB2Dictionary.db2ZOSV8xOrLater
+ || db2server == DB2Dictionary.db2UDBV82OrLater) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.booleanField, t0.byteField, "
- + "t0.charField, t0.dateField, t0.doubleField,"
- + " t0.floatField, t0.intField, t0.longField,"
- + " t0.shortField, t0.stringField FROM "
- + "AllFieldTypes t0 WHERE t0.id = \\? "
- + " FOR READ ONLY WITH RS USE AND KEEP UPDATE LOCKS"
- + " optimize for 1 row");
+ assertContainsSQL(" optimize for 1 row"
+ + " FOR READ ONLY WITH RS USE AND KEEP UPDATE LOCKS");
}
- else if (((DB2Dictionary) dict).getDb2ServerType() == 5) {
+ else if (db2server == DB2Dictionary.db2ISeriesV5R4OrLater) {
assertEquals(1, sql.size());
- assertSQL("SELECT t0.booleanField, t0.byteField, "
- + "t0.charField, t0.dateField, t0.doubleField,"
- + " t0.floatField, t0.intField, t0.longField,"
- + " t0.shortField, t0.stringField FROM "
- + "AllFieldTypes t0 WHERE t0.id = \\? "
+ assertContainsSQL(" optimize for 1 row"
+ " FOR READ ONLY WITH RS USE AND KEEP EXCLUSIVE LOCKS"
- + " optimize for 1 row");
+ );
}
else {
fail("OpenJPA currently only supports per-query isolation "
Modified: openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java?rev=574464&r1=574463&r2=574464&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java Mon Sep 10 22:32:37 2007
@@ -78,6 +78,21 @@
+ " should not have been executed in SQL statements: " + sql);
}
+ /**
+ * Confirm that the executed SQL String contains the specified sqlExp.
+ *
+ * @param sqlExp the SQL expression. E.g., "SELECT BADCOLUMN .*"
+ */
+ public void assertContainsSQL(String sqlExp) {
+ for (String statement : sql) {
+ if (statement.contains(sqlExp))
+ return;
+ }
+
+ fail("Expected regular expression <" + sqlExp + "> to be"
+ + " contained in SQL statements: " + sql);
+ }
+
public class Listener
extends AbstractJDBCListener {