[maven-release-plugin] copy for tag 2.1.0
git-svn-id: https://svn.apache.org/repos/asf/openjpa/tags/2.1.0@1071316 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
index a73586d..a3474de 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/DB2Dictionary.java
@@ -343,8 +343,10 @@
supportsLockingWithInnerJoin = true;
supportsLockingWithOuterJoin = true;
forUpdateClause = "WITH RR USE AND KEEP UPDATE LOCKS";
- if (maj >=9)
+
+ if (maj >= 9) {
supportsXMLColumn = true;
+ }
}
// platform specific settings
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java
index c702811..ebc549e 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/InformixDictionary.java
@@ -27,6 +27,8 @@
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,60 @@
// 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;
+ }
+}
diff --git a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java
index c92d753..dbe121c 100644
--- a/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java
+++ b/openjpa-jdbc/src/main/java/org/apache/openjpa/jdbc/sql/SQLServerDictionary.java
@@ -22,13 +22,9 @@
import java.sql.Clob;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
-import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
-import java.sql.Timestamp;
import java.sql.Types;
-import java.util.Calendar;
-import java.util.Set;
import org.apache.openjpa.jdbc.identifier.DBIdentifier;
import org.apache.openjpa.jdbc.kernel.JDBCStore;
@@ -95,7 +91,7 @@
// MSSQL 2008 supports new date, time and datetime2 types
// Use DATETIME2 which has 100ns vs. 3.333msec precision
dateTypeName = "DATETIME2";
- timeTypeName = "DATETIME";
+ timeTypeName = "DATETIME2";
timestampTypeName = "DATETIME2";
}
} else {
@@ -262,7 +258,7 @@
}
private void appendXmlValue(SQLBuffer buf, FilterValue val) {
- Class rc = Filters.wrap(val.getType());
+ Class<?> rc = Filters.wrap(val.getType());
int type = getJDBCType(JavaTypes.getTypeCode(rc), false);
boolean isXmlAttribute = (val.getXmlMapping() == null)
? false : val.getXmlMapping().isXmlAttribute();
diff --git a/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/strats/localizer.properties b/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/strats/localizer.properties
index 59c7316..11d08e5 100644
--- a/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/strats/localizer.properties
+++ b/openjpa-jdbc/src/main/resources/org/apache/openjpa/jdbc/meta/strats/localizer.properties
@@ -134,7 +134,8 @@
its "{1}" primary key field does not use a simple mapping.
unmapped-datastore-value: Instances of type "{0}" are not valid query \
parameters because the type is not mapped.
+cant-set-value: Field "{1}" of "{0}" can not be set to "{2}" value.
multi-column-version-unsupported:You have specified more than one column for \
version data, but the "{1}" version strategy does not support multi-column \
versioning.
-not-enum-field: Field "{0}" is expected to be a enum but actually is of type "{1}".
\ No newline at end of file
+not-enum-field: Field "{0}" is expected to be a enum but actually is of type "{1}".
diff --git a/openjpa-persistence-jdbc/pom.xml b/openjpa-persistence-jdbc/pom.xml
index c2d0335..dbcece5 100644
--- a/openjpa-persistence-jdbc/pom.xml
+++ b/openjpa-persistence-jdbc/pom.xml
@@ -615,6 +615,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>
<!--
diff --git a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java
index ea2cba3..cbde67d 100644
--- a/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java
+++ b/openjpa-persistence-jdbc/src/test/java/org/apache/openjpa/persistence/test/SQLListenerTestCase.java
@@ -221,6 +221,16 @@
buf.append(s).append("\r\n");
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,
diff --git a/openjpa-persistence-locking/pom.xml b/openjpa-persistence-locking/pom.xml
index 3fb0d22..67556cb 100644
--- a/openjpa-persistence-locking/pom.xml
+++ b/openjpa-persistence-locking/pom.xml
@@ -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>
<!--
diff --git a/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java b/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
index 061cb3d..9f99cf9 100644
--- a/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
+++ b/openjpa-persistence-locking/src/test/java/org/apache/openjpa/persistence/lockmgr/TestPessimisticLocks.java
@@ -40,6 +40,7 @@
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 @@
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 @@
// 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 @@
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);
diff --git a/openjpa-project/CHANGES.txt b/openjpa-project/CHANGES.txt
index eac87c9..2bf9feb 100644
--- a/openjpa-project/CHANGES.txt
+++ b/openjpa-project/CHANGES.txt
@@ -245,7 +245,8 @@
* [OPENJPA-1911] - InvalidStateException is thrown when merge an entity with derived identiy
* [OPENJPA-1918] - MetaDataRepository.preload() ignores class loader returned by PersistenceUnitInfo.getClassLoader()
* [OPENJPA-1923] - Allow flexible (non-standard) syntax for collection-valued parameters in IN() expresseion of JPQL query
-
+ * [OPENJPA-1935] - Informix lock exceptions are not mapped properly by OpenJPA
+ * [OPENJPA-1938] - Typo of time data type in SQLServerdictionary for MSSQL 2008
Improvement
-----------
diff --git a/openjpa-project/RELEASE-NOTES.html b/openjpa-project/RELEASE-NOTES.html
index 2d94fbe..bb9bb30 100644
--- a/openjpa-project/RELEASE-NOTES.html
+++ b/openjpa-project/RELEASE-NOTES.html
@@ -388,6 +388,10 @@
</li>
<li>[<a href='https://issues.apache.org/jira/browse/OPENJPA-1923'>OPENJPA-1923</a>] - Allow flexible (non-standard) syntax for collection-valued parameters in IN() expresseion of JPQL query
</li>
+<li>[<a href='https://issues.apache.org/jira/browse/OPENJPA-1935'>OPENJPA-1935</a>] - Informix lock exceptions are not mapped properly by OpenJPA
+</li>
+<li>[<a href='https://issues.apache.org/jira/browse/OPENJPA-1938'>OPENJPA-1938</a>] - Typo of time data type in SQLServerdictionary for MSSQL 2008
+</li>
</ul>
<h2> Improvement
diff --git a/openjpa-project/src/doc/manual/migration_considerations.xml b/openjpa-project/src/doc/manual/migration_considerations.xml
index 83dcb2a..898c5c1 100644
--- a/openjpa-project/src/doc/manual/migration_considerations.xml
+++ b/openjpa-project/src/doc/manual/migration_considerations.xml
@@ -143,20 +143,20 @@
enhancement and at runtime.
</para>
</section>
- <section id="setParameters">
+ <section id="setParameter">
<title>
- Query.setParameteres()
+ Query.setParameter()
</title>
<!-- See OPENJPA-1213 for details. -->
<para>
- The Query interface setParameters() method behavior has
- changed to throw an IllegalArgumentException if more
- parameter substitutions are supplied than defined in the
- createQuery() or createNamedQuery() call, as required by
- the JPA2 specification.
- OpenJPA 1.2.x and prior versions would silently ignore the
- supplied parameter substitutions and allow the Query to be
- processed.
+ The Query interface setParameter() method behavior has
+ changed to throw an IllegalArgumentException (as required
+ by the JPA specification) if more parameter substitutions
+ are supplied than defined in the createQuery(),
+ createNamedQuery(), or createNativeQuery() invocation.
+ OpenJPA 1.2.x and prior versions silently ignored these
+ extraneous parameter substitutions and allowed the Query
+ to be processed.
</para>
</section>
<section id="serialization">