Re: JDBC CTS 1.2.1

From: Vadim Nasardinov <vadimn(at)redhat(dot)com>
To: pgsql-jdbc(at)postgresql(dot)org
Subject: Re: JDBC CTS 1.2.1
Date: 2004-11-17 20:06:13
Message-ID: 200411171506.13490@vadim.nasardinov
Views: Raw Message | Whole Thread | Download mbox | Resend email
Thread:
Lists: pgsql-jdbc

On Tuesday 16 November 2004 18:47, Oliver Jowett wrote:
> It sounds like a bug in the CTS if it assumes it can run DDL (or for
> that matter any query) in a transaction after a failure. This is not
> specified by JDBC, AFAIK, and is demonstrably not a valid assumption
> to make under PostgreSQL.
>
> Is there any way to tell the CTS to run each bit of DDL in a
> separate transaction?

I'm not sure.

I (temporarily) patched the driver in a couple of places (see
attached) and ran the tests in the ejb and jsp vehicles to try and
figure out exactly where their behavior diverges. Initially, both
vehicles call connection.setAutoCommit(false), like so:

| at org.postgresql.jdbc2.AbstractJdbc2Connection.setAutoCommit(AbstractJdbc2Connection.java:598)
| at com.sun.enterprise.resource.JdbcConnectionAllocator.createResource(JdbcConnectionAllocator.java:75)
| at com.sun.enterprise.resource.PoolManagerImpl.getResourceFromPool(PoolManagerImpl.java:150)
| at com.sun.enterprise.resource.JdbcXAConnection.<init>(JdbcXAConnection.java:59)
| at com.sun.enterprise.resource.JdbcConnectionAllocator.createResource(JdbcConnectionAllocator.java:83)
| at com.sun.enterprise.resource.PoolManagerImpl.getResourceFromPool(PoolManagerImpl.java:150)
| at com.sun.enterprise.resource.PoolManagerImpl.getResource(PoolManagerImpl.java:100)
| at com.sun.enterprise.resource.JdbcDataSource.getConnection(JdbcDataSource.java:101)
| at com.sun.enterprise.resource.JdbcDataSource.getConnection(JdbcDataSource.java:66)
| at com.sun.cts.tests.jdbc.ee.common.DataSourceConnection.getConnection(DataSourceConnection.java:39)
| at com.sun.cts.tests.jdbc.ee.dbMeta.dbMeta1.dbMetaClient1.setup(dbMetaClient1.java:120)

From this point on, the bevahiors of the ejb and jsp vehicles differ.
The ejb vehicle does not make any further changes to the autocommit
setting. The jsp vehicle does. It calls
connection.setAutoCommit(true) like so:

| at org.postgresql.jdbc2.AbstractJdbc2Connection.setAutoCommit(AbstractJdbc2Connection.java:598)
| at com.sun.enterprise.resource.JdbcXAConnection$JdbcConnection.getCurrentConnection(JdbcXAConnection.java:507)
| at com.sun.enterprise.resource.JdbcXAConnection$JdbcConnection.createStatement(JdbcXAConnection.java:254)
| at com.sun.cts.tests.jdbc.ee.common.dbSchema.dropTables(dbSchema.java:196)
| at com.sun.cts.tests.jdbc.ee.common.dbSchema.createTable(dbSchema.java:94)
| at com.sun.cts.tests.jdbc.ee.common.dbSchema.createData(dbSchema.java:48)
| at com.sun.cts.tests.jdbc.ee.dbMeta.dbMeta1.dbMetaClient1.setup(dbMetaClient1.java:123)

This has the following effect. The method
AbstractJdbc2Statement#execute(Query query, ParameterList params, int
flags) has the following piece of code:

if (connection.getAutoCommit())
flags |= QueryExecutor.QUERY_SUPPRESS_BEGIN;

So, when the tests are run in the jsp vehicle, the
QUERY_SUPPRESSION_BEGIN bit is toggled on. In the ejb vehicle, it is
left unset.

In org.postgresql.core.v2.QueryExecutorImpl, we have

private void execute(V2Query query,
SimpleParameterList parameters,
ResultHandler handler,
int maxRows, int flags) throws SQLException {

// ...
String queryPrefix = null;
if (protoConnection.getTransactionState() ==
ProtocolConnection.TRANSACTION_IDLE &&
(flags & QueryExecutor.QUERY_SUPPRESS_BEGIN) == 0) {
queryPrefix = "BEGIN;";

// ...
}

Since the ejb vehicle does not set the QUERY_SUPPRESS_BEGIN flag, the
queryPrefix variable is set to "BEGIN;". The end result is that in
the case of the appclient, jsp, and servlet vehicles, each statement
is treated as its own transaction. This allows tests to proceed
merrily despite the failure of DROP TABLE statements.

In the case of ejb, each test runs in a single transaction which
includes DROP TABLE statements. As soon as a "DROP TABLE" statement
fails, the rest of the transaction goes up in flames and the test
fails.

Not sure if anything can be done about it.

> If you can issue a SAVEPOINT before the DROP TABLE and ROLLBACK TO
> SAVEPOINT on failure, it might work. But it seems unlikely you can
> do this without modifying the CTS itself, and you'd need to use 8.0
> for SAVEPOINT support.

Right. Moreover, Savepoint seems to only be present in jdbc3:
org/postgresql/jdbc3/PSQLSavepoint.java

As far as I can tell, CTS 1.2.1 is meant to be run against the RI of
J2EE 1.2.1. The latter only works under JDK 1.3. It has a hard-coded
version check.

> It might be useful to have an option to make the driver
> automatically generate SAVEPOINTs before each query (when autocommit
> is off), and do ROLLBACK TO SAVEPOINT or RELEASE SAVEPOINT as
> appropriate after the query completes. This gives behaviour more
> like other DBs at some cost to performance (I wouldn't want it to be
> on by default). Again, this would only work against an 8.0 server.

Yes, this sounds like it may work. But, like I said, you'd have to go
through some contortions to make CTS 1.2.1 work in this setup. It's
probably possible to run J2EE 1.2.1 under JDK 1.3 while at the same
time running CTS 1.2.1 under JDK 1.4 with a driver that supports
savepoints.

Alternatively, you could just say we're not even going to try to make
CTS 1.2.1 pass.

Vadim

Attachment Content-Type Size
track-autocommit.patch text/x-diff 1.7 KB
Log.java text/x-java 1003 bytes

In response to

Responses

Browse pgsql-jdbc by date

  From Date Subject
Next Message Kris Jurka 2004-11-17 20:12:15 Re: JDBC CTS 1.2.1
Previous Message Vadim Nasardinov 2004-11-17 19:34:28 Re: JDBC CTS 1.2.1