Re: [PATCHES] Fix JDBC test suite, set/get transaction isolation level test in ConnectionTest - Mailing list pgsql-jdbc

From Barry Lind
Subject Re: [PATCHES] Fix JDBC test suite, set/get transaction isolation level test in ConnectionTest
Date
Msg-id 3B9B23DB.4070301@xythos.com
Whole thread Raw
In response to Fix set/get transaction isolation level test in ConnectionTest  ("Rene Pijlman" <rene@lab.applinet.nl>)
List pgsql-jdbc
The patch looks OK to me.  (And yes a recent patch I did started using
set session characteristics, prior to that the code was explictly
setting the isolation level after every begin.)

thanks,
--Barry

Rene Pijlman wrote:
> Attached is a patch that fixes
> ConnectionTest.testTransactionIsolation() in the JDBC driver's
> test suite. This reduces the number of failures of the test
> suite from 7 to 6. The patch fixes the test case itself, rather
> than the driver.
>
> In addition to the change described in my posting below, I fixed
> the part of the test with autocommit enabled. The author of the
> test assumed that setting the transaction isolation level would
> have no effect, but in fact it does. Perhaps the test case
> worked with pre-7.1 behaviour, when the JDBC driver set the
> isolation level in every transaction, instead of using "set
> session characteristics". Anyway, now it works with a backend
> built from current CVS and the behaviour is JDBC compliant.
>
> I also extended the test case by changing the isolation level
> before beginning a transaction and verifying it inside the
> transaction.
>
> Regards,
> René Pijlman
>
> On Fri, 7 Sep 2001 17:56:59 +0200, I wrote on pgsql-jdbc:
>
>>The ConnectionTest test case in our own jdbc2 test suite fails
>>to set and get the transaction isolation level correctly. After
>>looking at the implementation I've come to the conclusion that
>>the test case itself is flawed, but I wanted to check my
>>conclusion with this list.
>>
>>What the test case does is:
>>
>>   con.setAutoCommit(false);
>>
>>con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE)
>>;
>>   assertEquals(Connection.TRANSACTION_SERIALIZABLE,
>>con.getTransactionIsolation());
>>
>>And this assertion fails because con.getTransactionIsolation()
>>returns TRANSACTION_READ_COMMITTED.
>>
>>The cause of this problem is that first a new transaction is
>>started (because of the setAutoCommit(false)) and then the
>>isolation level for this connection is changed. Internally
>>(since I tested against a 7.1 backend which supports SET
>>SESSION) the driver generates:
>>
>>   set session characteristics as transaction isolation level
>>serializable;
>>
>>And this changes only the default isolation level for future
>>transactions on this session, not the isolation level of the
>>current transaction. Therefore, getTransactionIsolation() in the
>>same transaction returns the still current isolation level READ
>>COMMITTED.
>>
>>Reading through JDBC documentation from Sun I found the best
>>explanation in the JDBC 3.0 Spec, final draft 3 (relevant
>>section quoted below). This says "It is recommended that drivers
>>implement the setTransactionIsolation method to change the
>>isolation level starting with the next transaction", and this is
>>in fact what our driver does.
>>
>>It also says "Committing the current transaction to make the
>>effect immediate is also a valid implementation", but I see no
>>reason to change the current behaviour to this alternative
>>implementation.
>>
>>And it says "The return value of the method
>>getTransactionIsolation should reflect the change in isolation
>>level when it actually occurs", and again, this is in fact what
>>our driver does.
>>
>>Note that applications can avoid this complication simply by
>>setting the transaction isolation level before starting a
>>transaction (before calling setAutoCommit(false)), as
>>recommended by JDBC.
>>
>>So I'm inclined to change the test case to allow (in fact,
>>require) the current behaviour. Any comments?
>>
>>-+-+-
>>Quote from the "JDBC ^(TM) 3.0 Specification, Proposed Final Draft
>>3"
>>http://java.sun.com/products/jdbc/download.html
>>
>>10.2.1 Using the setTransactionIsolation Method
>>The default transaction level for a Connection object is
>>determined by the driver
>>supplying the connection. Typically, it is the default
>>transaction level supported by
>>the underlying data source.
>>The Connection method setTransactionIsolation is provided to
>>allow JDBC
>>clients to change the transaction isolation level for a given
>>Connection object. The
>>new isolation level remains in effect for the remainder of the
>>session or until the next
>>invocation of the setTransactionIsolation method.
>>The result of invoking the method setTransactionIsolation in the
>>middle of a
>>transaction is implementation-defined.
>>The return value of the method getTransactionIsolation should
>>reflect the
>>change in isolation level when it actually occurs. It is
>>recommended that drivers
>>implement the setTransactionIsolation method to change the
>>isolation level
>>starting with the next transaction. Committing the current
>>transaction to make the
>>effect immediate is also a valid implementation.
>>It is possible for a given JDBC driver to not support all four
>>transaction isolation
>>levels (not counting TRANSACTION_NONE). If a driver does not
>>support the isolation
>>level specified in an invocation of setTransactionIsolation, it
>>is allowed to
>>substitute a higher, more restrictive transaction isolation
>>level. If a driver is unable to
>>substitute a higher transaction level, it throws an
>>SQLException. The
>>DatabaseMetaData method supportsTransactionIsolationLevel may be
>>used to determine whether or not the driver supports a given
>>level.
>>-+-+-
>>
>>Regards,
>>René Pijlman
>>
>>
>>---------------------------(end of broadcast)---------------------------
>>TIP 6: Have you searched our list archives?
>>
>>http://www.postgresql.org/search.mpl
>>
>
>
>
> ------------------------------------------------------------------------
>
> Index: org/postgresql/test/jdbc2/ConnectionTest.java
> ===================================================================
> RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/test/jdbc2/ConnectionTest.java,v
> retrieving revision 1.3
> diff -c -r1.3 ConnectionTest.java
> *** org/postgresql/test/jdbc2/ConnectionTest.java    2001/09/07 22:17:48    1.3
> --- org/postgresql/test/jdbc2/ConnectionTest.java    2001/09/08 13:59:54
> ***************
> *** 203,238 ****
>       }
>     }
>
> !   /**
> !    * Transaction Isolation Levels
> !    */
> !   public void testTransactionIsolation() {
> !     try {
> !       Connection con = JDBC2Tests.openDB();
> !
> !       con.setAutoCommit(false);
> !
> !       // These are the currently available ones
> !       con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
> !       assert(con.getTransactionIsolation()==Connection.TRANSACTION_SERIALIZABLE);
> !
> !       con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
> !       assert(con.getTransactionIsolation()==Connection.TRANSACTION_READ_COMMITTED);
> !
> !       // Now turn on AutoCommit. Transaction Isolation doesn't work outside of
> !       // a transaction, so they should return READ_COMMITTED at all times!
> !       con.setAutoCommit(true);
> !       con.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
> !       assert(con.getTransactionIsolation()==Connection.TRANSACTION_READ_COMMITTED);
> !
> !       con.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
> !       assert(con.getTransactionIsolation()==Connection.TRANSACTION_READ_COMMITTED);
> !
> !       JDBC2Tests.closeDB(con);
> !     } catch(SQLException ex) {
> !       assert(ex.getMessage(),false);
> !     }
> !   }
>
>     /**
>      * JDBC2 Type mappings
> --- 203,296 ----
>       }
>     }
>
> !     /**
> !      * Transaction Isolation Levels
> !      */
> !     public void testTransactionIsolation()
> !     {
> !         try
> !         {
> !             Connection con = JDBC2Tests.openDB();
> !
> !             // PostgreSQL defaults to READ COMMITTED
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_READ_COMMITTED );
> !
> !             // Begin a transaction
> !             con.setAutoCommit(false);
> !
> !             // The isolation level should not have changed
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_READ_COMMITTED );
> !
> !             // Now change the default for future transactions
> !             con.setTransactionIsolation( Connection.TRANSACTION_SERIALIZABLE );
> !
> !             // Since the call to setTransactionIsolation() above was made
> !             // inside the transaction, the isolation level of the current
> !             // transaction did not change. It affects only future transactions.
> !             // This behaviour is recommended by the JDBC spec.
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_READ_COMMITTED );
> !
> !             // Begin a new transaction
> !             con.commit();
> !
> !             // Now we should see the new isolation level
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_SERIALIZABLE );
> !
> !             // Repeat the steps above with the transition back to
> !             // READ COMMITTED.
> !             con.setTransactionIsolation(
> !                 Connection.TRANSACTION_READ_COMMITTED );
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_SERIALIZABLE );
> !             con.commit();
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_READ_COMMITTED );
> !
> !             // Now run some tests with autocommit enabled.
> !             con.setAutoCommit(true);
> !
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_READ_COMMITTED );
> !
> !             con.setTransactionIsolation( Connection.TRANSACTION_SERIALIZABLE );
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_SERIALIZABLE );
> !
> !             con.setTransactionIsolation(
> !                 Connection.TRANSACTION_READ_COMMITTED );
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_READ_COMMITTED );
> !
> !             // Test if a change of isolation level before beginning the
> !             // transaction affects the isolation level inside the transaction.
> !             con.setTransactionIsolation( Connection.TRANSACTION_SERIALIZABLE );
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_SERIALIZABLE );
> !             con.setAutoCommit(false);
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_SERIALIZABLE );
> !             con.setAutoCommit(true);
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_SERIALIZABLE );
> !             con.setTransactionIsolation(
> !                 Connection.TRANSACTION_READ_COMMITTED );
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_READ_COMMITTED );
> !             con.setAutoCommit(false);
> !             assertEquals( con.getTransactionIsolation(),
> !                           Connection.TRANSACTION_READ_COMMITTED );
> !
> !             JDBC2Tests.closeDB(con);
> !         }
> !         catch ( SQLException ex )
> !         {
> !             fail( ex.getMessage() );
> !         }
> !     }
>
>     /**
>      * JDBC2 Type mappings
>
>
> ------------------------------------------------------------------------
>
>
> ---------------------------(end of broadcast)---------------------------
> TIP 2: you can get off all lists at once with the unregister command
>     (send "unregister YourEmailAddressHere" to majordomo@postgresql.org)
>
> patchConnectionTest.diff
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> quoted-printable
>
>
> ------------------------------------------------------------------------
> Part 1.3
>
> Content-Type:
>
> text/plain
> Content-Encoding:
>
> binary
>
>



pgsql-jdbc by date:

Previous
From: Rene Pijlman
Date:
Subject: Re: getBlob problems with bytea type columns
Next
From: Rene Pijlman
Date:
Subject: Re: DatabaseMetadata problems