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 rh...@apache.org on 2006/05/17 03:09:11 UTC

svn commit: r407116 - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/ engine/org/apache/derby/impl/jdbc/ engine/org/apache/derby/loc/ shared/org/apache/derby/shared/common/reference/ testing/org/apache/derbyTesting/functionTests/tests/...

Author: rhillegas
Date: Tue May 16 18:09:10 2006
New Revision: 407116

URL: http://svn.apache.org/viewcvs?rev=407116&view=rev
Log:
DERBY-1328: Commit Narayanan's ClobBlob_free_v1.diff patch, implementing the LOB free() method introduced by JDBC4.

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/Clob.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java
    db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java
    db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties
    db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.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/ClobTest.java

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/client/org/apache/derby/client/am/Blob.java?rev=407116&r1=407115&r2=407116&view=diff
==============================================================================
--- 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 Tue May 16 18:09:10 2006
@@ -20,12 +20,17 @@
 
 package org.apache.derby.client.am;
 
+import java.io.IOException;
 import java.io.InputStream;
 import java.sql.SQLException;
-
 import org.apache.derby.shared.common.reference.SQLState;
 
 public class Blob extends Lob implements java.sql.Blob {
+    
+    //This boolean variable indicates whether the Blob object has
+    //been invalidated by calling free() on it
+    private boolean isValid = true;
+    
     //-----------------------------state------------------------------------------
 
     byte[] binaryString_ = null;
@@ -62,6 +67,9 @@
     // ---------------------------jdbc 2------------------------------------------
 
     public long length() throws SQLException {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
         try
         {
             synchronized (agent_.connection_) {
@@ -84,6 +92,9 @@
     // can return an array that may be have a length shorter than the supplied
     // length (no padding occurs)
     public byte[] getBytes(long pos, int length) throws SQLException {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
         try
         {
             synchronized (agent_.connection_) {
@@ -131,6 +142,9 @@
 
 
     public java.io.InputStream getBinaryStream() throws SQLException {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
         try
         {
             synchronized (agent_.connection_) {
@@ -162,6 +176,9 @@
     }
 
     public long position(byte[] pattern, long start) throws SQLException {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
         try
         {
             synchronized (agent_.connection_) {
@@ -192,6 +209,9 @@
     }
 
     public long position(java.sql.Blob pattern, long start) throws SQLException {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
         try
         {
             synchronized (agent_.connection_) {
@@ -229,6 +249,9 @@
 
 
     public int setBytes(long pos, byte[] bytes) throws SQLException {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
         try
         {
             synchronized (agent_.connection_) {
@@ -249,6 +272,9 @@
     }
 
     public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
         try
         {
             synchronized (agent_.connection_) {
@@ -325,6 +351,9 @@
     }
 
     public java.io.OutputStream setBinaryStream(long pos) throws SQLException {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
         synchronized (agent_.connection_) {
             if (agent_.loggingEnabled()) {
                 agent_.logWriter_.traceEntry(this, "setBinaryStream", (int) pos);
@@ -339,6 +368,9 @@
     }
 
     public void truncate(long len) throws SQLException {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
         try
         {
             synchronized (agent_.connection_) {
@@ -368,10 +400,37 @@
     }
 
     // -------------------------- JDBC 4.0 -----------------------------------
-
+    
+    /**
+     * This method frees the <code>Blob</code> object and releases the resources that 
+     * it holds. The object is invalid once the <code>free</code>
+     * method is called. If <code>free</code> is called multiple times, the subsequent
+     * calls to <code>free</code> are treated as a no-op.
+     * 
+     * @throws SQLException if an error occurs releasing
+     * the Blob's resources
+     */
     public void free()
         throws SQLException {
-        throw SQLExceptionFactory.notImplemented("free()");
+        
+        //calling free() on a already freed object is treated as a no-op
+        if (!isValid) return;
+        
+        //now that free has been called the Blob object is no longer
+        //valid
+        isValid = false;
+        
+        if(isBinaryStream()) {
+            try {
+                binaryStream_.close();
+            }
+            catch(IOException ioe) {
+                throw new SqlException(null, new ClientMessageId(SQLState.IO_ERROR_UPON_LOB_FREE)).getSQLException();
+            }
+        }
+        else {
+            binaryString_ = null;
+        }
     }
 
     public InputStream getBinaryStream(long pos, long length)
@@ -417,5 +476,18 @@
         }
 
         return true;
+    }
+    
+    /*
+     * Checks is isValid is true. If it is not true throws 
+     * a SQLException stating that a method has been called on
+     * an invalid LOB object
+     *
+     * throws SQLException if isvalid is not true.
+     */
+    private void checkValidity() throws SQLException{
+        if(!isValid)
+            throw new SqlException(null,new ClientMessageId(SQLState.LOB_OBJECT_INVALID))
+                                                  .getSQLException();
     }
 }

Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java?rev=407116&r1=407115&r2=407116&view=diff
==============================================================================
--- db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java (original)
+++ db/derby/code/trunk/java/client/org/apache/derby/client/am/Clob.java Tue May 16 18:09:10 2006
@@ -20,9 +20,9 @@
 
 package org.apache.derby.client.am;
 
+import java.io.IOException;
 import java.io.Reader;
 import java.sql.SQLException;
-
 import org.apache.derby.shared.common.reference.SQLState;
 
 public class Clob extends Lob implements java.sql.Clob {
@@ -47,6 +47,10 @@
     private PreparedStatement internalLengthStmt_ = null;
 
     protected String encoding_ = "UNICODE";
+    
+    //This boolean variable indicates whether the Clob object has
+    //been invalidated by calling free() on it
+    private boolean isValid = true;
 
     //---------------------constructors/finalizer---------------------------------
     public Clob(Agent agent, String string) {
@@ -144,6 +148,11 @@
     // ---------------------------jdbc 2------------------------------------------
     // Create another method lengthX for internal calls
     public long length() throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -170,6 +179,11 @@
     }
 
     public String getSubString(long pos, int length) throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -221,6 +235,11 @@
     }
 
     public java.io.Reader getCharacterStream() throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -253,6 +272,11 @@
     }
 
     public java.io.InputStream getAsciiStream() throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -285,6 +309,11 @@
     }
 
     public long position(String searchstr, long start) throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -330,6 +359,11 @@
     }
 
     public long position(java.sql.Clob searchstr, long start) throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -385,6 +419,11 @@
     //---------------------------- jdbc 3.0 -----------------------------------
 
     public int setString(long pos, String str) throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -405,6 +444,11 @@
     }
 
     public int setString(long pos, String str, int offset, int len) throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -463,6 +507,11 @@
     }
 
     public java.io.OutputStream setAsciiStream(long pos) throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -484,6 +533,11 @@
     }
 
     public java.io.Writer setCharacterStream(long pos) throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -505,6 +559,11 @@
     }
 
     public void truncate(long len) throws SQLException {
+        
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         try
         {
             synchronized (agent_.connection_) {
@@ -541,10 +600,64 @@
     }
 
     //---------------------------- jdbc 4.0 -------------------------------------
-
+    /**
+     * This method frees the <code>Clob</code> object and releases the resources the resources
+     * that it holds.  The object is invalid once the <code>free</code> method
+     * is called. If <code>free</code> is called multiple times, the
+     * subsequent calls to <code>free</code> are treated as a no-op.
+     *
+     * @throws SQLException if an error occurs releasing
+     * the Clob's resources
+     */
     public void free()
         throws SQLException {
-        throw SQLExceptionFactory.notImplemented("free()");
+        
+        //calling free() on a already freed object is treated as a no-op
+        if (!isValid) return;
+        
+        //now that free has been called the Blob object is no longer
+        //valid
+        isValid = false;
+        
+        if(isString()) {
+            string_ = null;
+            utf8String_ = null;
+        }
+        if(isAsciiStream()) {
+            try {
+                asciiStream_.close();
+            }
+            catch(IOException ioe) {
+                throw new SqlException(null, new ClientMessageId(SQLState.IO_ERROR_UPON_LOB_FREE)).getSQLException();
+            }
+        }
+        if(isUnicodeStream()) {
+            try {
+                unicodeStream_.close();
+            }
+            catch(IOException ioe) {
+                throw new SqlException(null, new ClientMessageId(SQLState.IO_ERROR_UPON_LOB_FREE)).getSQLException();
+            }
+        }
+        if(isCharacterStream()) {
+            try {
+                characterStream_.close();
+            }
+            catch(IOException ioe) {
+                throw new SqlException(null, new ClientMessageId(SQLState.IO_ERROR_UPON_LOB_FREE)).getSQLException();
+            }
+        }
+        
+        lengthInBytes_ = 0;
+        
+        if (internalLengthStmt_ != null) {
+            try {
+                internalLengthStmt_.closeX();
+            }
+            catch(SqlException sqle) {
+                throw sqle.getSQLException();
+            }
+        }
     }
 
     public Reader getCharacterStream(long pos, long length)
@@ -647,5 +760,18 @@
 
             length();
             return lengthInBytes_;
+    }
+    
+    /*
+     * Checks is isValid is true. If it is not true throws 
+     * a SQLException stating that a method has been called on
+     * an invalid LOB object
+     *
+     * throws SQLException if isvalid is not true.
+     */
+    private void checkValidity() throws SQLException{
+        if(!isValid)
+            throw new SqlException(null,new ClientMessageId(SQLState.LOB_OBJECT_INVALID))
+                                                  .getSQLException();
     }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java?rev=407116&r1=407115&r2=407116&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedBlob.java Tue May 16 18:09:10 2006
@@ -73,6 +73,7 @@
     // blob is either bytes or stream
     private boolean         isBytes;
     private InputStream     myStream;
+    
     /*
      * Length of the BLOB if known. Set to -1 if
      * the current length of the BLOB is not known.
@@ -89,6 +90,10 @@
     // and trashing them (to set the position of the stream etc.)
     private static int BLOB_BUF_SIZE = 4096;
     private byte buf[];
+    
+    //This boolean variable indicates whether the Blob object has
+    //been invalidated by calling free() on it
+    private boolean isValid = true;
 
     /*
       This constructor should only be called by EmbedResultSet.getBlob
@@ -215,6 +220,10 @@
     public long length()
         throws SQLException
     {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
+        
         if (myLength != -1)
             return myLength;
         
@@ -284,6 +293,10 @@
     public byte[] getBytes(long startPos, int length)
         throws SQLException
     {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
+        
         boolean pushStack = false;
         try
         {
@@ -369,6 +382,10 @@
     public java.io.InputStream getBinaryStream()
         throws SQLException
     {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
+        
         boolean pushStack = false;
         try
         {
@@ -420,6 +437,10 @@
     public long position(byte[] pattern, long start)
         throws SQLException
     {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
+        
         boolean pushStack = false;
         try
         {
@@ -515,6 +536,10 @@
     public long position(Blob pattern, long start)
         throws SQLException
     {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Blob object has been freed by calling free() on it
+        checkValidity();
+        
         boolean pushStack = false;
         try
         {
@@ -744,10 +769,34 @@
     //	JDBC 4.0	-	New public methods
     //
     /////////////////////////////////////////////////////////////////////////
-
+    /**
+     * This method frees the <code>Blob</code> object and releases the resources that 
+     * it holds. The object is invalid once the <code>free</code>
+     * method is called. If <code>free</code> is called multiple times, the subsequent
+     * calls to <code>free</code> are treated as a no-op.
+     * 
+     * @throws SQLException if an error occurs releasing
+     * the Blob's resources
+     */
     public void free()
         throws SQLException {
-        throw Util.notImplemented();
+        //calling free() on a already freed object is treated as a no-op
+        if (!isValid) return;
+        
+        //now that free has been called the Blob object is no longer
+        //valid
+        isValid = false;
+        
+        //initialialize length to default value -1
+        myLength = -1;
+        
+        //if it is a stream then close it.
+        //if a array of bytes then initialize it to null
+        //to free up space
+        if (!isBytes)
+            ((Resetable)myStream).closeStream();
+        else
+            myBytes = null;
     }
     
     /**
@@ -767,5 +816,17 @@
     public InputStream getBinaryStream(long pos, long length)
         throws SQLException {
         throw Util.notImplemented();
+    }
+    
+    /*
+     * Checks is isValid is true. If it is not true throws 
+     * a SQLException stating that a method has been called on
+     * an invalid LOB object
+     *
+     * throws SQLException if isvalid is not true.
+     */
+    private void checkValidity() throws SQLException{
+        if(!isValid)
+            throw newSQLException(SQLState.LOB_OBJECT_INVALID);
     }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java?rev=407116&r1=407115&r2=407116&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedClob.java Tue May 16 18:09:10 2006
@@ -74,6 +74,10 @@
     private boolean         isString;
     private InputStream     myStream;
     private String          myString;
+    
+    //This boolean variable indicates whether the Clob object has
+    //been invalidated by calling free() on it
+    private boolean isValid = true;
 
     /*
     This constructor should only be called by EmbedResultSet.getClob
@@ -136,6 +140,9 @@
 
     public long length() throws SQLException
     {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
         // if we have a string, not a stream
         if (isString)
             return myString.length();
@@ -199,6 +206,10 @@
 
     public String getSubString(long pos, int length) throws SQLException
     {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         if (pos < 1)
             throw Util.generateCsSQLException(
                 SQLState.BLOB_BAD_POSITION, new Long(pos));
@@ -268,6 +279,9 @@
 
     public java.io.Reader getCharacterStream() throws SQLException
     {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
 
         // if we have a string, not a stream
         if (isString)
@@ -306,6 +320,9 @@
 
     public java.io.InputStream getAsciiStream() throws SQLException
     {
+                //call checkValidity to exit by throwing a SQLException if
+                //the Clob object has been freed by calling free() on it
+                checkValidity();
 		return new ReaderToAscii(getCharacterStream());
     }
 
@@ -344,6 +361,10 @@
     public long position(String searchStr, long start)
         throws SQLException
     {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         boolean pushStack = false;
         try
         {
@@ -583,6 +604,10 @@
     public long position(Clob searchClob, long start)
         throws SQLException
     {
+        //call checkValidity to exit by throwing a SQLException if
+        //the Clob object has been freed by calling free() on it
+        checkValidity();
+        
         boolean pushStack = false;
         try
         {
@@ -745,7 +770,7 @@
 	public java.io.OutputStream setAsciiStream(long pos)
     throws SQLException
 	{
-		throw Util.notImplemented();
+                throw Util.notImplemented();
 	}
 
 	/**
@@ -784,10 +809,28 @@
     //	JDBC 4.0	-	New public methods
     //
     /////////////////////////////////////////////////////////////////////////
-	
+    /**
+     * This method frees the <code>Clob</code> object and releases the resources the resources
+     * that it holds.  The object is invalid once the <code>free</code> method
+     * is called. If <code>free</code> is called multiple times, the
+     * subsequent calls to <code>free</code> are treated as a no-op.
+     *
+     * @throws SQLException if an error occurs releasing
+     * the Clob's resources
+     */
     public void free()
         throws SQLException {
-        throw Util.notImplemented();
+        //calling free() on a already freed object is treated as a no-op
+        if (!isValid) return;
+        
+        //now that free has been called the Clob object is no longer
+        //valid
+        isValid = false;
+        
+        if (!isString)
+            ((Resetable)myStream).closeStream();
+        else
+            myString = null;
     }
 
     public java.io.Reader getCharacterStream(long pos, long length)
@@ -810,5 +853,16 @@
         }
 		return org.apache.derby.impl.jdbc.EmbedResultSet.noStateChangeException(t);
 	}
-
+        
+        /*
+         * Checks is isValid is true. If it is not true throws 
+         * a SQLException stating that a method has been called on
+         * an invalid LOB object
+         *
+         * throws SQLException if isValid is not true.
+         */
+        private void checkValidity() throws SQLException{
+            if(!isValid)
+                throw newSQLException(SQLState.LOB_OBJECT_INVALID);
+        }
 }

Modified: db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties?rev=407116&r1=407115&r2=407116&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/loc/messages_en.properties Tue May 16 18:09:10 2006
@@ -1215,6 +1215,8 @@
 XJ211.S=Non-recoverable chain-breaking exception occurred during batch processing. The batch is terminated non-atomically.
 XJ212.S=Invalid attribute syntax: {0}
 XJ213.C=The traceLevel connection property does not have a valid format for a number.
+XJ214.S=An IO Error occurred when calling free() on a CLOB or BLOB.
+XJ215.S=You cannot invoke other Clob/Blob methods after calling free.
 
 #XN - Network level messages
 XN001.S=Connection reset is not allowed when inside a unit of work.

Modified: db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java?rev=407116&r1=407115&r2=407116&view=diff
==============================================================================
--- db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java (original)
+++ db/derby/code/trunk/java/shared/org/apache/derby/shared/common/reference/SQLState.java Tue May 16 18:09:10 2006
@@ -1511,6 +1511,8 @@
     String BATCH_CHAIN_BREAKING_EXCEPTION = "XJ211.S";
     String INVALID_ATTRIBUTE_SYNTAX = "XJ212.S";
     String TRACELEVEL_FORMAT_INVALID = "XJ213.S";
+    String IO_ERROR_UPON_LOB_FREE = "XJ214.S";
+    String LOB_OBJECT_INVALID = "XJ215.S";
     
     //XN - Network-level messages
     String NET_CONNECTION_RESET_NOT_ALLOWED_IN_UNIT_OF_WORK         = "XN001.S";

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/BlobTest.java?rev=407116&r1=407115&r2=407116&view=diff
==============================================================================
--- 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 Tue May 16 18:09:10 2006
@@ -25,6 +25,90 @@
 import org.apache.derbyTesting.functionTests.util.BaseJDBCTestCase;
 
 import java.sql.*;
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/* This class is used to store the details of the methods that
+ * throw a SQLFeatureNotSupportedException in the implementation
+ * of java.sql.Blob.
+ *
+ * It store the following information about the methods
+ *
+ * a) Name
+ * b) Method Parameters
+ * c) Whether the method is exempted in the Embedded Sever
+ * d) Whether the method is exempted in the NetworkClient
+ *
+ */
+class ExemptBlobMD {
+    // The Name of the method
+    private String methodName_;
+    
+    // The parameters of the method
+    private Class [] params_;
+    
+    //Whether it is exempted in the 
+    //Client or the Embedded framework
+    private boolean isClientFramework_;
+    private boolean isEmbeddedFramework_;
+    
+    /**
+     * The Constructor for the ExemptBlobMD class that
+     * initialized the object with the details of the 
+     * methods that have been exempted
+     *
+     * @param methodName          A String that contains the name of the method
+     *                            that has been exempted.
+     * @param params              A array of Class that contains the parameters 
+     *                            of the methods.
+     * @param isClientFramework   true if the method is exempted in the 
+     *                            Client framework.
+     * @param isEmbeddedFramework true if the method is exempted in the 
+     *                            Embedded framework.
+     *
+     */
+    public ExemptBlobMD(String methodName,Class [] params,
+                            boolean isClientFramework,
+                            boolean isEmbeddedFramework) {
+        methodName_ = methodName;
+        params_ = params;
+        isClientFramework_ = isClientFramework;
+        isEmbeddedFramework_ = isEmbeddedFramework;
+    }
+    
+    /**
+     *
+     * Returns the name of the method.
+     *
+     * @return A String containing the name of the method.
+     *
+     */
+    public String getMethodName() { return methodName_; }
+    
+    /**
+     * Returns a array of Class containing the type of the parameters
+     * of this method. 
+     *
+     * @return A array of Class containing the type of the parameters 
+     *         of the method.
+     */
+    public Class [] getParams() { return params_; }
+    
+    /**
+     * Returns if the method is exempted from the Client Framework.
+     *
+     * @return true if the method is exempted from the Client Framework.
+     */
+    public boolean getIfClientFramework() { return isClientFramework_; }
+    
+     /**
+     * Returns if the method is exempted from the Embedded Framework.
+     *
+     * @return true if the method is exempted from the Embedded Framework.
+     */
+    public boolean getIfEmbeddedFramework() { return isEmbeddedFramework_; }
+}
 
 /*
  * Tests of the JDBC 4.0 specific <code>Blob</code> methods.
@@ -37,6 +121,29 @@
     /** Default connection used by the tests. */
     private Connection con = null;
     
+    // Initialize with the details of the method that are exempted from 
+    //throwing a SQLException when they are called after calling free()
+    //on a LOB.
+    
+    private ExemptBlobMD [] emd = new ExemptBlobMD [] {
+        new ExemptBlobMD( "getBinaryStream", new Class[] { long.class,long.class }
+                                                                   ,true,true ),
+        new ExemptBlobMD( "setBinaryStream", new Class[] { long.class },false,true ),
+        new ExemptBlobMD( "setBytes", new Class[] { long.class, byte[].class }
+                                                                   ,false,true ),
+        new ExemptBlobMD( "setBytes", new Class[] { long.class, byte[].class
+                                           , int.class, int.class },false,true ),
+        new ExemptBlobMD( "truncate", new Class[] { long.class },false,true),
+        new ExemptBlobMD( "free",null,true,true)
+    };
+    
+    // An HashMap that is indexed by the Method which facilitated easy
+    //search for whether the given method has been exempted from the
+    //LOB interface.
+    
+    private HashMap<Method,ExemptBlobMD> excludedMethodSet = 
+                            new HashMap<Method,ExemptBlobMD>();
+       
     /**
      * Create the test with the given name.
      *
@@ -50,8 +157,14 @@
         throws SQLException {
         con = getConnection();
         blob = BlobClobTestSetup.getSampleBlob(con);
+        
+        //call the buildHashSetMethod to initialize the 
+        //HashSet with the method signatures that are exempted 
+        //from throwing a SQLException after free has been called
+        //on the Clob object.
+        buildHashSet();
     }
-
+    
     public void tearDown()
         throws SQLException {
         blob = null;
@@ -61,16 +174,217 @@
         }
         con = null;
     }
-
-    public void testFreeNotImplemented()
+    
+    /**
+     * Builds the HashSet which will be used to test whether the given methods
+     * can be exempted or not
+     */
+    void buildHashSet() {
+        Class iface = Blob.class;
+        for(int i=0;i<emd.length;i++) {
+            try {
+                Method m = iface.getMethod(emd[i].getMethodName()
+                                                ,emd[i].getParams());
+                excludedMethodSet.put(m,emd[i]);
+            }
+            catch(NoSuchMethodException nsme) {
+                fail("The method could not be found in the interface");
+            }
+        }
+    }
+    
+    /**
+     * Tests the implementation for the free() method in the
+     * Blob interface.
+     * 
+     * @throws SQLException if an error occurs during releasing
+     *         the Blob resources
+     *
+     */
+    public void testFreeandMethodsAfterCallingFree()
         throws SQLException {
+        blob.free();
+        //testing the idempotence of the free() method
+        //the method can be called multiple times on
+        //the same instance. subsequent calls after 
+        //the first are treated as no-ops
+        blob.free();
+
+        //blob becomes invalid after the first call 
+        //to the free method so testing calling
+        //a method on this invalid object should throw
+        //an SQLException
+        buildMethodList(blob);
+    }
+    
+    /*
+     * 
+     * Enumerate the methods of the Blob interface and 
+     * get the list of methods present in the interface
+     * @param LOB an instance of the Blob interface implementation
+     */
+    void buildMethodList(Object LOB) {
+        //If the given method throws the correct exception
+        //set this to true and add it to the 
+        boolean valid = true;
+        
+        //create a list of the methods that fail the test
+        Vector<Method> methodList = new Vector<Method>();
+        
+        //The class whose methods are to be verified
+        Class clazz = Blob.class;
+        
+        //The list of the methods in the class that need to be invoked
+        //and verified
+        Method [] methods = clazz.getMethods();
+        
+        //Check each of the methods to ensure that
+        //they throw the required exception
+        for(int i=0;i<methods.length;i++) {
+            if(!checkIfExempted(methods[i])) {
+                valid = checkIfMethodThrowsSQLException(LOB,methods[i]);
+                
+                //add the method to the list if the method does
+                //not throw the required exception
+                if(valid == false) methodList.add(methods[i]);
+                
+                //reset valid
+                valid = true;
+            }
+        }
+        
+        if(!methodList.isEmpty()) {
+            int c=0;
+            String failureMessage = "The Following methods don't throw " +
+                "required exception - ";
+            for (Method m : methodList) {
+                c = c + 1;
+                if(c == methodList.size() && c != 1) 
+                    failureMessage += " & ";
+                else if(c != 1)
+                    failureMessage += " , ";
+                failureMessage += m.getName();
+            }
+            fail(failureMessage);
+        }
+    }
+    
+    /**
+     *Checks if the method throws a SQLFeatureNotSupportedException
+     *@param m The method object that needs to be verified to see if it 
+     *         is exempted
+     *@return true if the given method does not throw the required SQLException
+     *
+     */
+    boolean checkIfExempted(Method m) {
+        ExemptBlobMD md = excludedMethodSet.get(m);
+        
+        if(md != null && usingDerbyNetClient()) { 
+            if(md.getIfClientFramework()) 
+                return true;
+            else
+                return false;
+        } 
+        if(md != null && usingEmbedded()) {
+            if(md.getIfEmbeddedFramework())
+                return true;
+            else
+                return false;
+        }
+        return false;
+    }
+    
+    /**
+     * Checks if the invocation of the method throws a SQLExceptio
+     * as expected.
+     * @param LOB    the Object that implements the Blob interface
+     * @param method the method that needs to be tested to ensure
+     *               that it throws the correct exception
+     * @return true  If the method throws the SQLException required
+     *               after the free method has been called on the
+     *               LOB object
+     *
+     */
+    boolean checkIfMethodThrowsSQLException(Object LOB,Method method) {
         try {
-            blob.free();
-            fail("Blob.free() should not be implemented");
-        } catch (SQLFeatureNotSupportedException sfnse) {
-            // Do nothing, we are fine
+            method.invoke(LOB,getNullValues(method.getParameterTypes()));
+        } catch(Throwable e) {
+            if(e instanceof InvocationTargetException) {
+                Throwable cause = e.getCause();
+                if (cause instanceof SQLException ) {
+                    SQLException sqle = (SQLException)cause;
+                    if(sqle.getSQLState().equals("XJ215"))
+                        return true;
+                    else
+                        return false;
+                } else {
+                    return false;
+                }
+                
+            }
+        }
+        return false;
+    }
+    
+    /*
+     * Return a array of objects containing the default values for
+     * the objects passed in as parameters
+     * 
+     * @param parameterTypes an array containing the types of the parameter 
+     *                       to the method
+     * @return an array of Objects containing the null values for the 
+     *         parameter inputs
+     */
+    
+    Object[] getNullValues(Class<?> [] params) {
+        Object[] args = new Object[params.length];
+        for (int i = 0; i < params.length; i++) {
+            args[i] = getNullValueForType(params[i]);
         }
+        return args;
     }
+    
+    /*
+     * Returns the null value for the specific type
+     * 
+     * @param type the type of the parameter for which the null
+     *             value is required
+     * @return the null value for the specific type
+     * 
+     */
+     Object getNullValueForType(Class type)
+	{
+        if (!type.isPrimitive()) {
+            return null;
+        }
+        if (type == Boolean.TYPE) {
+            return Boolean.FALSE;
+        }
+        if (type == Character.TYPE) {
+            return new Character((char) 0);
+        }
+        if (type == Byte.TYPE) {
+            return new Byte((byte) 0);
+        }
+        if (type == Short.TYPE) {
+            return new Short((short) 0);
+        }
+        if (type == Integer.TYPE) {
+            return new Integer(0);
+        }
+        if (type == Long.TYPE) {
+            return new Long(0L);
+        }
+        if (type == Float.TYPE) {
+            return new Float(0f);
+        }
+        if (type == Double.TYPE) {
+            return new Double(0d);
+        }
+        fail("Don't know how to handle type " + type);
+        return null;            // unreachable statement
+    }
+    
     
     public void testGetBinaryStringLongNotImplemented()
         throws SQLException {

Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/ClobTest.java
URL: http://svn.apache.org/viewcvs/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/ClobTest.java?rev=407116&r1=407115&r2=407116&view=diff
==============================================================================
--- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/ClobTest.java (original)
+++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbc4/ClobTest.java Tue May 16 18:09:10 2006
@@ -26,6 +26,90 @@
 import org.apache.derbyTesting.functionTests.util.BaseJDBCTestCase;
 
 import java.sql.*;
+import java.io.*;
+import java.lang.reflect.*;
+import java.util.*;
+
+/* This class is used to store the details of the methods that
+ * throw a SQLFeatureNotSupportedException in the implementation
+ * of java.sql.Clob.
+ *
+ * It store the following information about the methods
+ *
+ * a) Name
+ * b) Method Parameters
+ * c) Whether the method is exempted in the Embedded Sever
+ * d) Whether the method is exempted in the NetworkClient
+ *
+ */
+class ExemptClobMD {
+    // The Name of the method
+    private String methodName_;
+    
+    // The parameters of the method
+    private Class [] params_;
+    
+    //Whether it is exempted in the 
+    //Client or the Embedded framework
+    private boolean isClientFramework_;
+    private boolean isEmbeddedFramework_;
+    
+    /**
+     * The Constructor for the ExemptClobMD class that
+     * initialized the object with the details of the 
+     * methods that have been exempted
+     *
+     * @param methodName          A String that contains the name of the method
+     *                            that has been exempted.
+     * @param params              A array of Class that contains the parameters 
+     *                            of the methods.
+     * @param isClientFramework   true if the method is exempted in the 
+     *                            Client framework.
+     * @param isEmbeddedFramework true if the method is exempted in the 
+     *                            Embedded framework.
+     *
+     */
+    public ExemptClobMD(String methodName,Class [] params,
+                            boolean isClientFramework,
+                            boolean isEmbeddedFramework) {
+        methodName_ = methodName;
+        params_ = params;
+        isClientFramework_ = isClientFramework;
+        isEmbeddedFramework_ = isEmbeddedFramework;
+    }
+    
+    /**
+     *
+     * Returns the name of the method.
+     *
+     * @return A String containing the name of the method.
+     *
+     */
+    public String getMethodName() { return methodName_; }
+    
+    /**
+     * Returns a array of Class containing the type of the parameters
+     * of this method. 
+     *
+     * @return A array of Class containing the type of the parameters 
+     *         of the method.
+     */
+    public Class [] getParams() { return params_; }
+    
+    /**
+     * Returns if the method is exempted from the Client Framework.
+     *
+     * @return true if the method is exempted from the Client Framework.
+     */
+    public boolean getIfClientFramework() { return isClientFramework_; }
+    
+    /**
+     * Returns if the method is exempted from the Embedded Framework.
+     *
+     * @return true if the method is exempted from the Embedded Framework.
+     */
+    public boolean getIfEmbeddedFramework() { return isEmbeddedFramework_; }
+}
 
 /*
  * Tests of the JDBC 4.0 specific <code>Clob</code> methods.
@@ -38,6 +122,27 @@
     /** Default connection used by the tests. */
     private Connection con = null;
     
+    // Initialize with the details of the method that are exempted from 
+    //throwing a SQLException when they are called after calling free()
+    //on a LOB.
+    
+    private ExemptClobMD [] emd = new ExemptClobMD [] {
+        new ExemptClobMD( "getCharacterStream", new Class[] { long.class, long.class } ,true,true),
+        new ExemptClobMD( "setAsciiStream",     new Class[] { long.class } ,false,true),
+	new ExemptClobMD( "setCharacterStream", new Class[] { long.class } ,true,true),
+	new ExemptClobMD( "setString",          new Class[] { long.class, String.class } ,false,true),
+	new ExemptClobMD( "setString",          new Class[] { long.class, String.class, int.class, int.class},false,true),
+	new ExemptClobMD( "truncate",           new Class[] { long.class },false,true),
+        new ExemptClobMD( "free",               null,true,true)
+    };
+    
+    // An HashMap that is indexed by the Method which facilitated easy
+    //search for whether the given method has been exempted from the
+    //LOB interface.
+    
+    private HashMap<Method,ExemptClobMD> excludedMethodSet = 
+                            new HashMap<Method,ExemptClobMD>();
+    
     /**
      * Create the test with the given name.
      *
@@ -51,6 +156,12 @@
         throws SQLException {
         con = getConnection();
         clob = BlobClobTestSetup.getSampleClob(con);
+        
+        //call the buildHashSetMethod to initialize the 
+        //HashSet with the method signatures that are exempted 
+        //from throwing a SQLException after free has been called
+        //on the Clob object.
+        buildHashSet();
     }
 
     public void tearDown()
@@ -62,15 +173,217 @@
         }
         con = null;
     }
-
-    public void testFreeNotImplemented()
+    
+    /**
+     * Builds the HashSet which will be used to test whether the given methods
+     * can be exempted or not
+     */
+    void buildHashSet() {
+        Class iface = Clob.class;
+        for(int i=0;i<emd.length;i++) {
+            try {
+                Method m = iface.getMethod(emd[i].getMethodName()
+                                                ,emd[i].getParams());
+                excludedMethodSet.put(m,emd[i]);
+            }
+            catch(NoSuchMethodException nsme) {
+                fail("The method could not be found in the interface");
+            }
+        }
+    }
+    
+    /**
+     * Tests the implementation for the free() method in the
+     * Clob interface.
+     * 
+     * @throws SQLException if an error occurs during releasing
+     *         the Clob resources
+     *
+     */
+    public void testFreeandMethodsAfterCallingFree()
         throws SQLException {
-        try {
+            InputStream asciiStream = clob.getAsciiStream();
+            Reader charStream  = clob.getCharacterStream();
+            clob.free();
+            //testing the idempotence of the free() method
+            //the method can be called multiple times on
+            //the same instance. subsequent calls after 
+            //the first are treated as no-ops
             clob.free();
-            fail("Clob.free() should not be implemented");
-        } catch (SQLFeatureNotSupportedException sfnse) {
-            // Do nothing, we are fine
+            
+            //clob becomes invalid after the first call 
+            //to the free method so testing calling
+            //a method on this invalid object should throw
+            //an SQLException
+            buildMethodList(clob);
+    }
+    
+    /*
+     * 
+     * Enumerate the methods of the Clob interface and 
+     * get the list of methods present in the interface
+     * @param LOB an instance of the Clob interface implementation
+     */
+    void buildMethodList(Object LOB) {
+        //If the given method throws the correct exception
+        //set this to true and add it to the 
+        boolean valid = true;
+        
+        //create a list of the methods that fail the test
+        Vector<Method> methodList = new Vector<Method>();
+        
+        //The class whose methods are to be verified
+        Class clazz = Clob.class;
+        
+        //The list of the methods in the class that need to be invoked
+        //and verified
+        Method [] methods = clazz.getMethods();
+        
+        //Check each of the methods to ensure that
+        //they throw the required exception
+        for(int i=0;i<methods.length;i++) {
+            if(!checkIfExempted(methods[i])) {
+                valid = checkIfMethodThrowsSQLException(LOB,methods[i]);
+                
+                //add the method to the list if the method does
+                //not throw the required exception
+                if(valid == false) methodList.add(methods[i]);
+                
+                //reset valid
+                valid = true;
+            }
+        }
+        
+        if(!methodList.isEmpty()) {
+            int c=0;
+            String failureMessage = "The Following methods don't throw " +
+                "required exception - ";
+            for (Method m : methodList) {
+                c = c + 1;
+                if(c == methodList.size() && c != 1) 
+                    failureMessage += " & ";
+                else if(c != 1)
+                    failureMessage += " , ";
+                failureMessage += m.getName();
+            }
+            fail(failureMessage);
+        }
+    }
+    
+    /**
+     *Checks if the method throws a SQLFeatureNotSupportedException
+     *@param m The method object that needs to be verified to see if it 
+     *         is exempted
+     *@return true if the given method does not throw the required SQLException
+     *
+     */
+    boolean checkIfExempted(Method m) {
+        ExemptClobMD md = excludedMethodSet.get(m);
+        
+        if(md != null && usingDerbyNetClient()) { 
+            if(md.getIfClientFramework()) 
+                return true;
+            else
+                return false;
+        } 
+        if(md != null && usingEmbedded()) {
+            if(md.getIfEmbeddedFramework())
+                return true;
+            else
+                return false;
+        }
+        return false;
+    }
+    
+    /*
+     * Checks if the invocation of the method throws a SQLExceptio
+     * as expected.
+     * @param LOB    the Object that implements the Blob interface
+     * @param method the method that needs to be tested to ensure
+     *               that it throws the correct exception
+     * @return true  If the method throws the SQLException required
+     *               after the free method has been called on the
+     *               LOB object
+     *
+     */
+    boolean checkIfMethodThrowsSQLException(Object LOB,Method method) {
+        try {
+            method.invoke(LOB,getNullValues(method.getParameterTypes()));
+        } catch(Throwable e) {
+            if(e instanceof InvocationTargetException) {
+                Throwable cause = e.getCause();
+                if (cause instanceof SQLException ) {
+                    SQLException sqle = (SQLException)cause;
+                    if(sqle.getSQLState().equals("XJ215"))
+                        return true;
+                    else
+                        return false;
+                } else {
+                    return false;
+                }
+                
+            }
+        }
+        return false;
+    }
+    
+    /*
+     * Return a array of objects containing the default values for
+     * the objects passed in as parameters
+     * 
+     * @param parameterTypes an array containing the types of the parameter 
+     *                       to the method
+     * @return an array of Objects containing the null values for the 
+     *         parameter inputs
+     */
+    
+    Object[] getNullValues(Class<?> [] params) {
+        Object[] args = new Object[params.length];
+        for (int i = 0; i < params.length; i++) {
+            args[i] = getNullValueForType(params[i]);
+        }
+        return args;
+    }
+    
+    /*
+     * Returns the null value for the specific type
+     * 
+     * @param type the type of the parameter for which the null
+     *             value is required
+     * @return the null value for the specific type
+     * 
+     */
+     Object getNullValueForType(Class type)
+	{
+        if (!type.isPrimitive()) {
+            return null;
+        }
+        if (type == Boolean.TYPE) {
+            return Boolean.FALSE;
+        }
+        if (type == Character.TYPE) {
+            return new Character((char) 0);
+        }
+        if (type == Byte.TYPE) {
+            return new Byte((byte) 0);
+        }
+        if (type == Short.TYPE) {
+            return new Short((short) 0);
+        }
+        if (type == Integer.TYPE) {
+            return new Integer(0);
+        }
+        if (type == Long.TYPE) {
+            return new Long(0L);
+        }
+        if (type == Float.TYPE) {
+            return new Float(0f);
+        }
+        if (type == Double.TYPE) {
+            return new Double(0d);
         }
+        fail("Don't know how to handle type " + type);
+        return null;            // unreachable statement
     }
     
     public void testGetCharacterStreamLongNotImplemented()