You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@openjpa.apache.org by jr...@apache.org on 2011/02/08 17:42:22 UTC
svn commit: r1068472 - in /openjpa/trunk:
openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/
openjpa-persistence-jdbc/
openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/
openjpa-persistence-locking/ openjpa-persistence-loc...
Author: jrbauer
Date: Tue Feb 8 16:42:22 2011
New Revision: 1068472
URL: http://svn.apache.org/viewvc?rev=1068472&view=rev
Log:
OPENJPA-1935 Updated Informix dictionary to examine nested SQL exceptions when determining whether a generic exception is a lock exception. Added Informix JDBC profile to jdbc and locking poms.
Modified:
openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java
openjpa/trunk/openjpa-persistence-jdbc/pom.xml
openjpa/trunk/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java
openjpa/trunk/openjpa-persistence-locking/pom.xml
openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
Modified: openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java?rev=1068472&r1=1068471&r2=1068472&view=diff
==============================================================================
--- openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java (original)
+++ openjpa/trunk/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java Tue Feb 8 16:42:22 2011
@@ -27,6 +27,8 @@ import java.sql.Statement;
import java.sql.Types;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Map;
+import java.util.Set;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.identifier.DBIdentifier.DBIdentifierType;
@@ -393,12 +395,61 @@ public class InformixDictionary
// SQL State of IX000 is a general purpose Informix error code
// category, so only return Boolean.TRUE if we match SQL Codes
// recoverable = Boolean.FALSE;
- if ((subtype == StoreException.LOCK && ex.getErrorCode() == -154)
+ if ((subtype == StoreException.LOCK && checkNestedErrorCodes(ex, "IX000", -154))
||(subtype == StoreException.QUERY && ex.getErrorCode() == -213)) {
return false;
}
return super.isFatalException(subtype, ex);
}
+
+ /**
+ * Specialized matchErrorState method for Informix. Informix exceptions are
+ * typically nested multiple levels deep. Correct determination of the exception type requires
+ * inspection of nested exceptions to determine the root cause. A list of Informix (IDS v10) error codes
+ * can be found here:
+ *
+ * http://publib.boulder.ibm.com/infocenter/idshelp/v10/index.jsp?topic=/com.ibm.em.doc/errors_ids100.html
+ *
+ * @param errorStates classification of SQL error states by their specific nature. The keys of the
+ * map represent one of the constants defined in {@link StoreException}. The value corresponding to
+ * a key represent the set of SQL Error States representing specific category of database error.
+ * This supplied map is sourced from <code>sql-error-state-codes.xml</xml> and filtered the
+ * error states for the current database.
+ *
+ * @param ex original SQL Exception as raised by the database driver.
+ *
+ * @return A constant indicating the category of error as defined in {@link StoreException}.
+ */
+ protected int matchErrorState(Map<Integer,Set<String>> errorStates, SQLException ex) {
+ // Informix SQLState IX000 is a general SQLState that applies to many possible conditions
+ // If the underlying cause is also an IX000 with error code:
+ // -107 ISAM error: record is locked. || -154 ISAM error: Lock Timeout Expired.
+ // the exception type is LOCK.
+ if (checkNestedErrorCodes(ex, "IX000", -107, -154)) {
+ return StoreException.LOCK;
+ }
+ return super.matchErrorState(errorStates, ex);
+ }
+
+ private boolean checkNestedErrorCodes(SQLException ex, String sqlState, int...errorCodes) {
+ SQLException cause = ex;
+ int level = 0;
+ // Query at most 5 exceptions deep to prevent infinite iteration exception loops
+ // Typically, the root exception is at level 3.
+ while (cause != null && level < 5) {
+ String errorState = cause.getSQLState();
+ if (sqlState == null || sqlState.equals(errorState)) {
+ for (int ec : errorCodes) {
+ if (cause.getErrorCode() == ec) {
+ return true;
+ }
+ }
+ }
+ cause = cause.getNextException();
+ level++;
+ }
+ return false;
+ }
}
Modified: openjpa/trunk/openjpa-persistence-jdbc/pom.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-jdbc/pom.xml?rev=1068472&r1=1068471&r2=1068472&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-jdbc/pom.xml (original)
+++ openjpa/trunk/openjpa-persistence-jdbc/pom.xml Tue Feb 8 16:42:22 2011
@@ -627,6 +627,74 @@
</repositories>
</profile>
+ <!-- Profile for testing Informix with the Informix JDBC Driver -->
+ <profile>
+ <!--
+ Example Informix profile. You can use this profile if you:
+ 1) have the Informix JDBC artifacts installed in a local repo and
+ supply the URL:
+ -Dids.maven.repo=http://my.local.repo
+ 2) have a copy of the Informix driver and run the following
+ commands :
+ mvn install:install-file -Dfile=${path to ifxjdbc.jar} \
+ -DgroupId=com.informix \
+ -DartifactId=informix-driver \
+ -Dversion=3.70 \
+ -Dpackaging=jar
+
+ You must also set the following properties:
+ -Dopenjpa.ids.url=jdbc:informix-sqli://<HOST>:<PORT>:informixserver=<INFORMIXSERVER>;database=<DBNAME>
+ -Dopenjpa.ids.username=<ids_uid>
+ -Dopenjpa.ids.password=<ids_pwd>
+
+ Optionally, you can override the default Informix groupId,
+ artifactIds and version by also supplying the following
+ properties:
+ -Dids.groupid=com.informix
+ -Dids.driver.artifactid=informix-driver
+ -Dids.version=3.70
+ -->
+ <id>test-ids-informix</id>
+ <activation>
+ <property>
+ <name>test-ids-informix</name>
+ </property>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>${ids.groupid}</groupId>
+ <artifactId>${ids.driver.artifactid}</artifactId>
+ <version>${ids.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <properties>
+ <ids.maven.repo>http://not.a.real.repository</ids.maven.repo>
+ <ids.groupid>com.informix</ids.groupid>
+ <ids.driver.artifactid>informix-driver</ids.driver.artifactid>
+ <ids.version>3.70</ids.version>
+ <connection.driver.name>com.informix.jdbc.IfxDriver</connection.driver.name>
+ <connection.url>${openjpa.ids.url}</connection.url>
+ <connection.username>${openjpa.ids.username}</connection.username>
+ <connection.password>${openjpa.ids.password}</connection.password>
+ </properties>
+ <repositories>
+ <repository>
+ <id>ids.repository</id>
+ <name>Informix Repository</name>
+ <url>${ids.maven.repo}</url>
+ <layout>default</layout>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ <releases>
+ <enabled>true</enabled>
+ <checksumPolicy>ignore</checksumPolicy>
+ </releases>
+ </repository>
+ </repositories>
+ </profile>
+
<!-- Profile for testing with Oracle DB -->
<profile>
<!--
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=1068472&r1=1068471&r2=1068472&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 Tue Feb 8 16:42:22 2011
@@ -222,6 +222,16 @@ public abstract class SQLListenerTestCas
return buf.toString();
}
+ /**
+ * Returns the last SQL executed or the empty string if the list is
+ * empty.
+ */
+ public String getLastSQL(List<String> list) {
+ if (list != null && list.size() > 0)
+ return list.get(list.size() -1);
+ return "";
+ }
+
public enum SQLAssertType {
SQL, NotSQL, ContainsSQL, AllSQLInOrder, AllExactSQLInOrder,
AllSQLAnyOrder, NoneSQLAnyOrder, AnySQLAnyOrder
Modified: openjpa/trunk/openjpa-persistence-locking/pom.xml
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-locking/pom.xml?rev=1068472&r1=1068471&r2=1068472&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-locking/pom.xml (original)
+++ openjpa/trunk/openjpa-persistence-locking/pom.xml Tue Feb 8 16:42:22 2011
@@ -594,6 +594,74 @@
</repositories>
</profile>
+ <!-- Profile for testing Informix with the Informix JDBC Driver -->
+ <profile>
+ <!--
+ Example Informix profile. You can use this profile if you:
+ 1) have the Informix JDBC artifacts installed in a local repo and
+ supply the URL:
+ -Dids.maven.repo=http://my.local.repo
+ 2) have a copy of the Informix driver and run the following
+ commands :
+ mvn install:install-file -Dfile=${path to ifxjdbc.jar} \
+ -DgroupId=com.informix \
+ -DartifactId=informix-driver \
+ -Dversion=3.70 \
+ -Dpackaging=jar
+
+ You must also set the following properties:
+ -Dopenjpa.ids.url=jdbc:informix-sqli://<HOST>:<PORT>:informixserver=<INFORMIXSERVER>;database=<DBNAME>
+ -Dopenjpa.ids.username=<ids_uid>
+ -Dopenjpa.ids.password=<ids_pwd>
+
+ Optionally, you can override the default Informix groupId,
+ artifactIds and version by also supplying the following
+ properties:
+ -Dids.groupid=com.informix
+ -Dids.driver.artifactid=informix-driver
+ -Dids.version=3.70
+ -->
+ <id>test-ids-informix</id>
+ <activation>
+ <property>
+ <name>test-ids-informix</name>
+ </property>
+ </activation>
+ <dependencies>
+ <dependency>
+ <groupId>${ids.groupid}</groupId>
+ <artifactId>${ids.driver.artifactid}</artifactId>
+ <version>${ids.version}</version>
+ <scope>test</scope>
+ </dependency>
+ </dependencies>
+ <properties>
+ <ids.maven.repo>http://not.a.real.repository</ids.maven.repo>
+ <ids.groupid>com.informix</ids.groupid>
+ <ids.driver.artifactid>informix-driver</ids.driver.artifactid>
+ <ids.version>3.70</ids.version>
+ <connection.driver.name>com.informix.jdbc.IfxDriver</connection.driver.name>
+ <connection.url>${openjpa.ids.url}</connection.url>
+ <connection.username>${openjpa.ids.username}</connection.username>
+ <connection.password>${openjpa.ids.password}</connection.password>
+ </properties>
+ <repositories>
+ <repository>
+ <id>ids.repository</id>
+ <name>Informix Repository</name>
+ <url>${ids.maven.repo}</url>
+ <layout>default</layout>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ <releases>
+ <enabled>true</enabled>
+ <checksumPolicy>ignore</checksumPolicy>
+ </releases>
+ </repository>
+ </repositories>
+ </profile>
+
<!-- Profile for testing with Oracle DB -->
<profile>
<!--
Modified: openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
URL: http://svn.apache.org/viewvc/openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java?rev=1068472&r1=1068471&r2=1068472&view=diff
==============================================================================
--- openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java (original)
+++ openjpa/trunk/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java Tue Feb 8 16:42:22 2011
@@ -40,6 +40,7 @@ import org.apache.openjpa.jdbc.conf.JDBC
import org.apache.openjpa.jdbc.sql.DB2Dictionary;
import org.apache.openjpa.jdbc.sql.DBDictionary;
import org.apache.openjpa.jdbc.sql.DerbyDictionary;
+import org.apache.openjpa.jdbc.sql.InformixDictionary;
import org.apache.openjpa.lib.log.Log;
import org.apache.openjpa.persistence.LockTimeoutException;
import org.apache.openjpa.persistence.OpenJPAEntityManagerFactorySPI;
@@ -396,14 +397,14 @@ public class TestPessimisticLocks extend
String firstName1 = (String) q1.getSingleResult();
//Expected sql for Derby is:
//SELECT t0.firstName FROM Employee t0 WHERE (t0.id = CAST(? AS BIGINT)) FOR UPDATE WITH RR
- String SQL1 = toString(sql);
+ String SQL1 = getLastSQL(sql);
// run the second time
resetSQL();
Query q2 = em.createQuery(jpql);
q2.setLockMode(LockModeType.PESSIMISTIC_WRITE);
String firstName2 = (String) q2.getSingleResult();
- String SQL2 = toString(sql);
+ String SQL2 = getLastSQL(sql);
assertEquals(SQL1, SQL2);
em.getTransaction().commit();
}
@@ -422,10 +423,18 @@ public class TestPessimisticLocks extend
// Only run this test on DB2 and Derby for now. It could cause
// the test to hang on other platforms.
if (!(dict instanceof DerbyDictionary ||
- dict instanceof DB2Dictionary)) {
+ dict instanceof DB2Dictionary ||
+ dict instanceof InformixDictionary)) {
return;
}
+ // Informix currently requires the lock timeout to be set directly on the dictionary
+ if (dict instanceof InformixDictionary) {
+ InformixDictionary ifxDict = (InformixDictionary)((JDBCConfiguration)emf.getConfiguration()).getDBDictionaryInstance();
+ ifxDict.lockModeEnabled = true;
+ ifxDict.lockWaitSeconds = 5;
+ }
+
EntityManager em = emf.createEntityManager();
resetSQL();
@@ -459,8 +468,11 @@ public class TestPessimisticLocks extend
Map<String,Object> props = new HashMap<String,Object>();
// This property does not have any effect on Derby for the locking
// condition produced by this test. Instead, Derby uses the
- // lock timeout value specified in the config (pom.xml)
- props.put("javax.persistence.lock.timeout", 5000);
+ // lock timeout value specified in the config (pom.xml). On Informix,
+ // the dictionary level timeout (set above) will be used.
+ if (!(dict instanceof InformixDictionary)) {
+ props.put("javax.persistence.lock.timeout", 5000);
+ }
em.getTransaction().begin();
getLog().trace("Main: refresh with force increment");
em.refresh(ve, LockModeType.PESSIMISTIC_FORCE_INCREMENT, props);