You are viewing a plain text version of this content. The canonical link for it is here.
Posted to derby-commits@db.apache.org by ka...@apache.org on 2007/05/19 19:59:20 UTC

svn commit: r539784 - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/ client/org/apache/derby/client/net/ testing/org/apache/derbyTesting/functionTests/tests/jdbc4/

Author: kahatlen
Date: Sat May 19 10:59:19 2007
New Revision: 539784

URL: http://svn.apache.org/viewvc?view=rev&rev=539784
Log:
DERBY-2496: Implement Blob support for Locators

Modified Blob tests so that they also work when locators are
enabled. Fixed two bugs in the network protocol. Patch contributed by
Øystein Grøvlen.

File-by-file explanation of changes:

M java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java
    - Adjusted tests to not expect Blob objects to be valid after
      transaction commit.

M java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java
    - Adjusted tests to not expect Blob objects to be valid after
      transaction commit.
    - Rewrote testSetBlobLengthless to take advantage of the existence of
      Connection.createBlob

M java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/ResultSetTest.java
    - Adjusted tests to not expect Blob objects to be valid after
      transaction commit.

M java/client/org/apache/derby/client/net/NetCursor.java
    - If the column value is zero, a locator was not sent. Instead, this
      means that the length of the LOB is 0. Changed locator() to return
      INVALID_LOCATOR when the column value is zero.

M java/client/org/apache/derby/client/net/NetStatementRequest.java
    - If column is not nullable, a non-nullable locator must be requested.
      Otherwise, the server will send an extra byte for nullability which
      is not expected by the client.

M java/client/org/apache/derby/client/am/BlobLocatorOutputStream.java
    - Added an assert that checks that the underlying Blob object is
      locator based.

M java/client/org/apache/derby/client/am/Blob.java
    - Add buffering for InputStreams by wrapping BlobLocatorInputStream in
      a BufferedInputStream. (Doing the same for OutputStreams is not that
      straight-forward since that requires that the stream is flushed
      before the statement is executed.)

M java/client/org/apache/derby/client/am/BlobLocatorInputStream.java
    - Removed a TAB. Client code is supposed to be a TAB-free zone!

Modified:
    db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java
    db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorOutputStream.java
    db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java
    db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementRequest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java
    db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/ResultSetTest.java

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java?view=diff&rev=539784&r1=539783&r2=539784
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java Sat May 19 10:59:19 2007
@@ -21,11 +21,12 @@
 
 package org.apache.derby.client.am;
 
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.sql.SQLException;
-import java.util.ArrayList;
 
 import org.apache.derby.shared.common.reference.SQLState;
 
@@ -267,7 +268,8 @@
         {
             return binaryStream_;
         } else if (isLocator()) {
-            return new BlobLocatorInputStream(agent_.connection_, this);
+            return new BufferedInputStream(
+                    new BlobLocatorInputStream(agent_.connection_, this));
         } else {  // binary string
             return new java.io.ByteArrayInputStream(binaryString_, dataOffset_,
                                            binaryString_.length - dataOffset_);
@@ -654,10 +656,11 @@
                 
                 InputStream retVal;
                 if (isLocator()) {
-                    retVal = new BlobLocatorInputStream(agent_.connection_, 
-                                                        this, 
-                                                        pos, 
-                                                        length);
+                    retVal = new BufferedInputStream(
+                            new BlobLocatorInputStream(agent_.connection_,
+                                                       this,
+                                                       pos,
+                                                       length));
                 } else {  // binary string
                     retVal = new java.io.ByteArrayInputStream
                         (binaryString_, 

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java?view=diff&rev=539784&r1=539783&r2=539784
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorInputStream.java Sat May 19 10:59:19 2007
@@ -26,7 +26,7 @@
 
 import java.io.IOException;
 
-import org.apache.derby.iapi.services.sanity.SanityManager;
+import org.apache.derby.shared.common.sanity.SanityManager;
 
 /**
  * An <code>InputStream</code> that will use an locator to fetch the
@@ -61,7 +61,7 @@
         throws SqlException
     {        
         if (SanityManager.DEBUG) {
-        	SanityManager.ASSERT(blob.isLocator());
+            SanityManager.ASSERT(blob.isLocator());
         }
         this.connection = connection;
         this.blob = blob;

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorOutputStream.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorOutputStream.java?view=diff&rev=539784&r1=539783&r2=539784
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorOutputStream.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/BlobLocatorOutputStream.java Sat May 19 10:59:19 2007
@@ -22,6 +22,8 @@
 package org.apache.derby.client.am;
 import java.io.IOException;
 
+import org.apache.derby.shared.common.sanity.SanityManager;
+
 /**
  * An <code>OutputStream</code> that will use an locator to write
  * bytes to the Blob value on the server.
@@ -51,6 +53,10 @@
     public BlobLocatorOutputStream(Connection connection, Blob blob, long pos)
         throws SqlException
     {
+        if (SanityManager.DEBUG) {
+            SanityManager.ASSERT(blob.isLocator());
+        }
+
         if (pos-1 > blob.sqlLength()) {
             throw new IndexOutOfBoundsException();
         }

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java?view=diff&rev=539784&r1=539783&r2=539784
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetCursor.java Sat May 19 10:59:19 2007
@@ -1060,7 +1060,8 @@
     {
         int locator = get_INTEGER(column);
         // If Lob value was sent instead of locator, highest bit will be set
-        if ((locator & 0x8000) == 0x8000) { 
+        // Zero is not a valid locator, it indicates a zero length value
+        if (((locator & 0x8000) == 0x8000) || (locator == 0)) {
             return Lob.INVALID_LOCATOR;
         } else {
             return locator;

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementRequest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementRequest.java?view=diff&rev=539784&r1=539783&r2=539784
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementRequest.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/net/NetStatementRequest.java Sat May 19 10:59:19 2007
@@ -632,14 +632,19 @@
         for (int i=0; i<numVars; ++i) {
             switch (resultSetMetaData.types_[i]) {
                 case java.sql.Types.BLOB:
-                    lidAndLengths[i][0] = DRDAConstants.DRDA_TYPE_NLOBLOC;
+                    lidAndLengths[i][0] = (resultSetMetaData.nullable_[i])
+                            ? DRDAConstants.DRDA_TYPE_NLOBLOC
+                            : DRDAConstants.DRDA_TYPE_LOBLOC;
                     lidAndLengths[i][1] = 4;
                     break;
  
                 case java.sql.Types.CLOB:
+                    lidAndLengths[i][0] = (resultSetMetaData.nullable_[i])
                     // Locators for Clob has not yet been implemented
-                    // lidAndLengths[i][0] = DRDAConstants.DRDA_TYPE_NCLOBLOC;
-                    lidAndLengths[i][0] = DRDAConstants.DRDA_TYPE_NLOBCMIXED;
+//                            ? DRDAConstants.DRDA_TYPE_NLOBLOC
+//                            : DRDAConstants.DRDA_TYPE_LOBLOC;
+                            ? DRDAConstants.DRDA_TYPE_NLOBCMIXED
+                            : DRDAConstants.DRDA_TYPE_LOBCMIXED;
                     lidAndLengths[i][1] = 4;
                     break;
             }

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java?view=diff&rev=539784&r1=539783&r2=539784
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java Sat May 19 10:59:19 2007
@@ -156,6 +156,10 @@
     public void setUp() 
         throws SQLException {
 
+        // Life span of Blob objects are limited by the transaction.  Need
+        // autocommit off so Blob objects survive closing of result set.
+        getConnection().setAutoCommit(false);
+
         blob = BlobClobTestSetup.getSampleBlob(getConnection());
         
         //call the buildHashSetMethod to initialize the 
@@ -409,10 +413,10 @@
         InputStream is_1 = blob.getBinaryStream(2L,5L);
         InputStream is_2 = new java.io.ByteArrayInputStream(BYTES1,1,5);
 
+        assertEquals(is_2,is_1);
+
         rs.close();
         st.close();
-
-        assertEquals(is_2,is_1);
     }
     
     /**

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java?view=diff&rev=539784&r1=539783&r2=539784
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/PreparedStatementTest.java Sat May 19 10:59:19 2007
@@ -472,8 +472,11 @@
      */
     public void testSetBlob()
             throws IOException, SQLException {
-        //insert default values into the table
+        // Life span of Blob objects are limited by the transaction.  Need
+        // autocommit off so Blob objects survive execution of next statement.
+        getConnection().setAutoCommit(false);
         
+        //insert default values into the table
         InputStream is = new java.io.ByteArrayInputStream(BYTES);
         is.reset();
         
@@ -509,34 +512,26 @@
     /**
      * Insert <code>Blob</code> without specifying length and read it back
      * for verification.
-     *
-     * Beacuse we don't yet support <code>Connection.createBlob</code> in the
-     * client driver, we must first insert data into the database and read back
-     * a <code>Blob</code> object. This object is then inserted into the
-     * database again.
      */
     public void testSetBlobLengthless()
             throws IOException, SQLException {
-        // Insert test data.
-        InputStream is = new ByteArrayInputStream(BYTES);
-        psInsertBlob.setInt(1, key);
-        psInsertBlob.setBinaryStream(2, is);
-        psInsertBlob.execute();
-        is.close();
-        // Must fetch Blob from database because we don't support
-        // Connection.createBlob on the client yet.
-        psFetchBlob.setInt(1, key);
-        ResultSet rs = psFetchBlob.executeQuery();
-        assertTrue("No results retrieved", rs.next());
-        Blob insertBlob = rs.getBlob(1);
+        // Life span of Blob objects are the transaction.  Need autocommit off
+        // to have Blob objects survive execution of next statement.
+        getConnection().setAutoCommit(false);
+        // Create Blob to be inserted
+        Blob insertBlob = getConnection().createBlob();
+        OutputStream os = insertBlob.setBinaryStream(1);
+        os.write(BYTES);
         int secondKey = requestKey();
         psInsertBlob.setInt(1, secondKey);
         psInsertBlob.setBlob(2, insertBlob);
         psInsertBlob.execute();
+        os.close();
+        psInsertBlob.close();
 
         // Read back test data from database.
         psFetchBlob.setInt(1, secondKey);
-        rs = psFetchBlob.executeQuery();
+        ResultSet rs = psFetchBlob.executeQuery();
         assertTrue("No results retrieved", rs.next());
         Blob blobRetrieved = rs.getBlob(1);
 
@@ -753,12 +748,11 @@
         psInsertBlob.setBinaryStream(2, is, BYTES.length);
         psInsertBlob.executeUpdate();
         
-        //Now query to retrieve the Clob
+        // Now query to retrieve the Blob
         psFetchBlob.setInt(1, key);
         ResultSet rs = psFetchBlob.executeQuery();
         rs.next();
         Blob blobRetrieved = rs.getBlob(1);
-        rs.close();
         
         try {
             InputStream is_ret = blobRetrieved.getBinaryStream();
@@ -766,6 +760,7 @@
         } catch(IOException ioe) {
             fail("IOException while reading the Clob from the database");
         }
+        rs.close(); // Because of autocommit, this will invalidate blobRetrieved
         
         for(int i=0;i<BYTES.length;i++) {
             assertEquals("Error in inserting data into the Blob",BYTES[i],bytes1[i]);

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/ResultSetTest.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/ResultSetTest.java?view=diff&rev=539784&r1=539783&r2=539784
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/ResultSetTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/ResultSetTest.java Sat May 19 10:59:19 2007
@@ -1051,6 +1051,11 @@
      */
     public void testUpdateBlob()
     throws Exception {
+
+        // Life span of Blob objects are limited by the transaction.  Need
+        // autocommit off so Blob objects survive execution of next statement.
+        getConnection().setAutoCommit(false);
+
         //Byte array in which the returned bytes from
         //the Database after the update are stored. This
         //array is then checked to determine if it
@@ -1339,6 +1344,10 @@
      */
     public void testUpdateBlobStringParameterName()
     throws Exception {
+        // Life span of Blob objects are limited by the transaction.  Need
+        // autocommit off so Blob objects survive execution of next statement.
+        getConnection().setAutoCommit(false);
+
         //Byte array in which the returned bytes from
         //the Database after the update are stored. This
         //array is then checked to determine if it