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 2010/08/05 14:46:51 UTC

svn commit: r982585 - in /db/derby/code/trunk: ./ java/engine/org/apache/derby/iapi/types/

Author: rhillegas
Date: Thu Aug  5 12:46:51 2010
New Revision: 982585

URL: http://svn.apache.org/viewvc?rev=982585&view=rev
Log:
DERBY-4754: Make the getObject() methods of Derby's LOBs always return jdbc LOBs.

Added:
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialBlob.java   (with props)
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java   (with props)
Modified:
    db/derby/code/trunk/NOTICE
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLBinary.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLBlob.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java
    db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLClob.java

Modified: db/derby/code/trunk/NOTICE
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/NOTICE?rev=982585&r1=982584&r2=982585&view=diff
==============================================================================
--- db/derby/code/trunk/NOTICE (original)
+++ db/derby/code/trunk/NOTICE Thu Aug  5 12:46:51 2010
@@ -36,7 +36,8 @@ http://www.itl.nist.gov/div897/ctg/sql_f
 
 The JDBC apis for small devices and JDBC3 (under java/stubs/jsr169 and
 java/stubs/jdbc3) were produced by trimming sources supplied by the
-Apache Harmony project. The following notice covers the Harmony sources:
+Apache Harmony project. In addition, the Harmony SerialBlob and
+SerialClob implementations are used. The following notice covers the Harmony sources:
 
 Portions of Harmony were originally developed by
 Intel Corporation and are licensed to the Apache Software

Added: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialBlob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialBlob.java?rev=982585&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialBlob.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialBlob.java Thu Aug  5 12:46:51 2010
@@ -0,0 +1,274 @@
+/*
+
+   Derby - Class org.apache.derby.iapi.types.SQLClob
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to you under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derby.iapi.types;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+import java.sql.Blob;
+import java.sql.SQLException;
+
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.error.StandardException;
+
+/**
+ * Copied from the Harmony project's implementation of javax.sql.rowset.serial.SerialBlob
+ * at subversion revision 946981.
+ */
+public class HarmonySerialBlob implements Blob, Serializable, Cloneable {
+
+    private static final long serialVersionUID = -8144641928112860441L;
+
+    // required by serialized form
+    private byte[] buf;
+
+    // required by serialized form
+    private Blob blob;
+
+    // required by serialized form
+    private long len;
+
+    // required by serialized form
+    private long origLen;
+
+    /**
+     * Constructs an instance by the given <code>blob</code>
+     * 
+     * @param blob
+     *            the given blob
+     * @throws SQLException
+     *             if an error is encountered during serialization
+     * @throws SQLException
+     *             if <code>blob</code> is null
+     */
+    public HarmonySerialBlob(Blob blob) throws SQLException {
+        if (blob == null) { throw new IllegalArgumentException(); }
+        
+        this.blob = blob;
+        buf = blob.getBytes(1, (int) blob.length());
+        len = buf.length;
+        origLen = len;
+    }
+
+    /**
+     * Constructs an instance by the given <code>buf</code>
+     * 
+     * @param buf
+     *            the given buffer
+     * @throws SQLException
+     *             if an error is encountered during serialization
+     * @throws SQLException
+     *             if a SQL error is encountered
+     */
+    public HarmonySerialBlob(byte[] buf) throws SQLException {
+        this.buf = new byte[buf.length];
+        len = buf.length;
+        origLen = len;
+        System.arraycopy(buf, 0, this.buf, 0, (int) len);
+    }
+
+    /**
+     * Returns an input stream of this SerialObject.
+     * 
+     * @throws SQLException
+     *             if an error is encountered
+     */
+    public InputStream getBinaryStream() throws SQLException {
+        return new ByteArrayInputStream(buf);
+    }
+
+    /**
+     * Returns a copied array of this SerialObject, starting at the
+     * <code> pos </code> with the given <code> length</code> number. If
+     * <code> pos </code> + <code> length </code> - 1 is larger than the length
+     * of this SerialObject array, the <code> length </code> will be shortened
+     * to the length of array - <code>pos</code> + 1.
+     * 
+     * @param pos
+     *            the starting position of the array to be copied.
+     * @param length
+     *            the total length of bytes to be copied
+     * @throws SQLException
+     *             if an error is encountered
+     */
+    public byte[] getBytes(long pos, int length) throws SQLException {
+
+        if (pos < 1 || pos > len)
+        {
+            throw makeSQLException( SQLState.BLOB_BAD_POSITION, new Object[] {new Long(pos)} );
+        }
+        if (length < 0)
+        {
+            throw makeSQLException( SQLState.BLOB_NONPOSITIVE_LENGTH, new Object[] {new Integer(length)} );
+        }
+
+        if (length > len - pos + 1) {
+            length = (int) (len - pos + 1);
+        }
+        byte[] copiedArray = new byte[length];
+        System.arraycopy(buf, (int) pos - 1, copiedArray, 0, length);
+        return copiedArray;
+    }
+
+    /**
+     * Gets the number of bytes in this SerialBlob object.
+     * 
+     * @return an long value with the length of the SerialBlob in bytes
+     * @throws SQLException
+     *             if an error is encoutnered
+     */
+    public long length() throws SQLException {
+        return len;
+    }
+
+    /**
+     * Search for the position in this Blob at which a specified pattern begins,
+     * starting at a specified position within the Blob.
+     * 
+     * @param pattern
+     *            a Blob containing the pattern of data to search for in this
+     *            Blob
+     * @param start
+     *            the position within this Blob to start the search, where the
+     *            first position in the Blob is 1
+     * @return a long value with the position at which the pattern begins. -1 if
+     *         the pattern is not found in this Blob.
+     * @throws SQLException
+     *             if an error occurs accessing the Blob
+     * @throws SQLException
+     *             if an error is encountered
+     */
+    public long position(Blob pattern, long start) throws SQLException {
+        byte[] patternBytes = pattern.getBytes(1, (int) pattern.length());
+        return position(patternBytes, start);
+    }
+
+    /**
+     * Search for the position in this Blob at which the specified pattern
+     * begins, starting at a specified position within the Blob.
+     * 
+     * @param pattern
+     *            a byte array containing the pattern of data to search for in
+     *            this Blob
+     * @param start
+     *            the position within this Blob to start the search, where the
+     *            first position in the Blob is 1
+     * @return a long value with the position at which the pattern begins. -1 if
+     *         the pattern is not found in this Blob.
+     * @throws SQLException
+     *             if an error is encountered
+     * @throws SQLException
+     *             if an error occurs accessing the Blob
+     */
+    public long position(byte[] pattern, long start) throws SQLException {
+        if (start < 1 || len - (start - 1) < pattern.length) {
+            return -1;
+        }
+
+        for (int i = (int) (start - 1); i <= (len - pattern.length); ++i) {
+            if (match(buf, i, pattern)) {
+                return i + 1;
+            }
+        }
+        return -1;
+    }
+
+    /*
+     * Returns true if the bytes array contains exactly the same elements from
+     * start position to start + subBytes.length as subBytes. Otherwise returns
+     * false.
+     */
+    private boolean match(byte[] bytes, int start, byte[] subBytes) {
+        for (int i = 0; i < subBytes.length;) {
+            if (bytes[start++] != subBytes[i++]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public OutputStream setBinaryStream(long pos) throws SQLException {
+        if (blob == null) { throw new IllegalStateException(); }
+        OutputStream os = blob.setBinaryStream(pos);
+        if (os == null) { throw new IllegalStateException(); }
+        return os;
+    }
+
+    public int setBytes(long pos, byte[] theBytes) throws SQLException {
+        return setBytes(pos, theBytes, 0, theBytes.length);
+    }
+
+    public int setBytes(long pos, byte[] theBytes, int offset, int length)
+            throws SQLException {
+        if (pos < 1 || length < 0 || pos > (len - length + 1))
+        {
+            throw makeSQLException( SQLState.BLOB_BAD_POSITION, new Object[] {new Long(pos)} );
+        }
+        if (offset < 0 || length < 0 || offset > (theBytes.length - length))
+        {
+            throw makeSQLException( SQLState.BLOB_INVALID_OFFSET, new Object[] {new Integer(offset)} );
+        }
+        System.arraycopy(theBytes, offset, buf, (int) pos - 1, length);
+        return length;
+    }
+
+    public void truncate(long length) throws SQLException {
+        if (length > this.len)
+        {
+            throw makeSQLException( SQLState.BLOB_LENGTH_TOO_LONG, new Object[] {new Long(len)} );
+        }
+        buf = getBytes(1, (int) length);
+        len = length;
+    }
+
+    public void free() throws SQLException {
+        throw new UnsupportedOperationException("Not supported");
+    }
+
+    public InputStream getBinaryStream(long pos, long length)
+            throws SQLException {
+        if (len < 0)
+        {
+            throw makeSQLException( SQLState.BLOB_NONPOSITIVE_LENGTH, new Object[] {new Long(len)} );
+        }
+        if (length < 0)
+        {
+            throw makeSQLException( SQLState.BLOB_NONPOSITIVE_LENGTH, new Object[] {new Long(length)} );
+        }
+        if (pos < 1 || pos + length > len)
+        {
+            throw makeSQLException( SQLState.POS_AND_LENGTH_GREATER_THAN_LOB, new Object[] {new Long(pos), new Long(length)} );
+        }
+        return new ByteArrayInputStream(buf, (int) (pos - 1), (int) length);
+    }
+
+    /**
+     * Create a SQLException from Derby message arguments.
+     */
+    public static SQLException makeSQLException( String messageID, Object[] args )
+    {
+        StandardException se = StandardException.newException( messageID, args );
+
+        return new SQLException( se.getMessage(), se.getSQLState() );
+    }
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialBlob.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java?rev=982585&view=auto
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java (added)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java Thu Aug  5 12:46:51 2010
@@ -0,0 +1,237 @@
+/*
+
+   Derby - Class org.apache.derby.iapi.types.SQLClob
+
+   Licensed to the Apache Software Foundation (ASF) under one or more
+   contributor license agreements.  See the NOTICE file distributed with
+   this work for additional information regarding copyright ownership.
+   The ASF licenses this file to you under the Apache License, Version 2.0
+   (the "License"); you may not use this file except in compliance with
+   the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+   Unless required by applicable law or agreed to in writing, software
+   distributed under the License is distributed on an "AS IS" BASIS,
+   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+   See the License for the specific language governing permissions and
+   limitations under the License.
+
+ */
+
+package org.apache.derby.iapi.types;
+
+import java.io.CharArrayReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Serializable;
+import java.io.Writer;
+import java.sql.Clob;
+import java.sql.SQLException;
+
+import org.apache.derby.iapi.reference.SQLState;
+import org.apache.derby.iapi.error.StandardException;
+
+/**
+ * Copied from the Harmony project's implementation of javax.sql.rowset.serial.SerialClob
+ * at subversion revision 946981.
+ */
+public class HarmonySerialClob implements Clob, Serializable, Cloneable {
+
+    // required by serialized form
+    private static final long serialVersionUID = -1662519690087375313L;
+
+    private char[] buf;
+
+    // required by serialized form
+    private Clob clob;
+
+    private long len;
+
+    // required by serialized form
+    private long origLen;
+
+    public HarmonySerialClob(char[] ch) {
+        buf = new char[ch.length];
+        origLen = ch.length;
+        len = origLen;
+        System.arraycopy(ch, 0, buf, 0, (int) len);
+    }
+
+    public HarmonySerialClob(Clob clob) throws SQLException {
+        Reader characterStream;
+
+        if (clob == null) { throw new IllegalArgumentException(); }
+        if ((characterStream = clob.getCharacterStream()) == null
+                && clob.getAsciiStream() == null) { throw new IllegalArgumentException(); }
+
+        this.clob = clob;
+        origLen = clob.length();
+        len = origLen;
+        buf = new char[(int) len];
+        try {
+            characterStream.read(buf);
+        } catch (IOException e) {
+            SQLException se = new SQLException("SerialClob: "
+                    + e.getMessage());
+
+            se.initCause(e);
+            throw se;
+        }
+    }
+
+    public long length() throws SQLException {
+        checkValidation();
+        return len;
+    }
+
+    public InputStream getAsciiStream() throws SQLException {
+        checkValidation();
+        if (clob == null) { throw new IllegalStateException(); }
+        return clob.getAsciiStream();
+    }
+
+    public Reader getCharacterStream() throws SQLException {
+        checkValidation();
+        return new CharArrayReader(buf);
+    }
+
+    public String getSubString(long pos, int length) throws SQLException {
+        checkValidation();
+        if (length < 0)
+        {
+            throw HarmonySerialBlob.makeSQLException( SQLState.BLOB_NONPOSITIVE_LENGTH, new Object[] {new Integer(length)} );
+        }
+        if (pos < 1 || pos > len || pos + length > len + 1)
+        {
+            throw HarmonySerialBlob.makeSQLException( SQLState.BLOB_BAD_POSITION, new Object[] {new Long(pos)} );
+        }
+        try {
+            return new String(buf, (int) (pos - 1), length);
+        } catch (StringIndexOutOfBoundsException e) {
+            throw new SQLException();
+        }
+    }
+
+    public long position(Clob searchClob, long start) throws SQLException {
+        checkValidation();
+        String searchString = searchClob.getSubString(1, (int) searchClob
+                .length());
+        return position(searchString, start);
+    }
+
+    public long position(String searchString, long start)
+            throws SQLException, SQLException {
+        checkValidation();
+        if (start < 1 || len - (start - 1) < searchString.length()) {
+            return -1;
+        }
+        char[] pattern = searchString.toCharArray();
+        for (int i = (int) start - 1; i < len; i++) {
+            if (match(buf, i, pattern)) {
+                return i + 1;
+            }
+        }
+        return -1;
+    }
+
+    /*
+     * Returns true if the chars array contains exactly the same elements from
+     * start position to start + pattern.length as pattern. Otherwise returns
+     * false.
+     */
+    private boolean match(char[] chars, int start, char[] pattern) {
+        for (int i = 0; i < pattern.length;) {
+            if (chars[start++] != pattern[i++]) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public OutputStream setAsciiStream(long pos) throws SQLException {
+        checkValidation();
+        if (clob == null) { throw new IllegalStateException(); }
+        OutputStream os = clob.setAsciiStream(pos);
+        if (os == null) { throw new IllegalStateException(); }
+        return os;
+    }
+
+    public Writer setCharacterStream(long pos) throws SQLException {
+        checkValidation();
+        if (clob == null) { throw new IllegalStateException(); }
+        Writer writer = clob.setCharacterStream(pos);
+        if (writer == null) { throw new IllegalStateException(); }
+        return writer;
+    }
+
+    public int setString(long pos, String str) throws SQLException {
+        checkValidation();
+        return setString(pos, str, 0, str.length());
+    }
+
+    public int setString(long pos, String str, int offset, int length)
+            throws SQLException {
+        checkValidation();
+        if (pos < 1)
+        {
+            throw HarmonySerialBlob.makeSQLException( SQLState.BLOB_BAD_POSITION, new Object[] {new Long(pos)} );
+        }
+        if (length < 0)
+        {
+            throw HarmonySerialBlob.makeSQLException( SQLState.BLOB_NONPOSITIVE_LENGTH, null );
+        }
+        if (pos > (len - length + 1))
+        {
+            throw HarmonySerialBlob.makeSQLException( SQLState.BLOB_POSITION_TOO_LARGE, null );
+        }
+        if (offset < 0 || offset > (str.length() - length))
+        {
+            throw HarmonySerialBlob.makeSQLException( SQLState.BLOB_INVALID_OFFSET, null );
+        }
+        if (length > len + offset)
+        {
+            throw HarmonySerialBlob.makeSQLException( SQLState.BLOB_INVALID_OFFSET, null );
+        }
+        str.getChars(offset, offset + length, buf, (int) pos - 1);
+        return length;
+    }
+
+    public void truncate(long length) throws SQLException {
+        checkValidation();
+        if (length < 0)
+        {
+            throw HarmonySerialBlob.makeSQLException( SQLState.BLOB_NONPOSITIVE_LENGTH, new Object[] {new Long(length)} );
+        }
+        if (length > len)
+        {
+            throw HarmonySerialBlob.makeSQLException( SQLState.BLOB_LENGTH_TOO_LONG, new Object[] {new Long(length)} );
+        }
+        char[] truncatedBuffer = new char[(int) length];
+        System.arraycopy(buf, 0, truncatedBuffer, 0, (int) length);
+        buf = truncatedBuffer;
+        len = length;
+    }
+
+    public void free() throws SQLException {
+        if (this.len != -1) {
+            this.len = -1;
+            this.clob = null;
+            this.buf = null;
+        }
+    }
+
+    public Reader getCharacterStream(long pos, long length) throws SQLException {
+        checkValidation();
+        return new CharArrayReader(buf, (int) pos, (int) length);
+    }
+
+    private void checkValidation() throws SQLException {
+        if (len == -1)
+        {
+            throw HarmonySerialBlob.makeSQLException( SQLState.LOB_OBJECT_INVALID, null );
+        }
+    }
+}

Propchange: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/HarmonySerialClob.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLBinary.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLBinary.java?rev=982585&r1=982584&r2=982585&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLBinary.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLBinary.java Thu Aug  5 12:46:51 2010
@@ -265,19 +265,6 @@ abstract class SQLBinary
 		return dataValue;
 	}
 	
-     /**
-      * Return a JDBC Blob. Only implemented to support DERBY-2201.
-      */
-    public Object getObject()
-        throws StandardException
-    {
-        // the generated code for the DERBY-2201 codepath expects to get a Blob
-        // back.
-
-        if ( _blobValue != null ) { return _blobValue; }
-        else { return super.getObject(); }
-    }
-    
 	/**
 	 * length in bytes
 	 *

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLBlob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLBlob.java?rev=982585&r1=982584&r2=982585&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLBlob.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLBlob.java Thu Aug  5 12:46:51 2010
@@ -152,6 +152,32 @@ public class SQLBlob extends SQLBinary
 			return new SQLBlob();
         }
 
+     /**
+      * Return a JDBC Blob. Originally implemented to support DERBY-2201.
+      */
+    public Object getObject()
+        throws StandardException
+    {
+        // the generated code for the DERBY-2201 codepath expects to get a Blob
+        // back.
+        if ( _blobValue != null ) { return _blobValue; }
+        else
+        {
+            byte[] bytes = getBytes();
+
+            if ( bytes == null ) { return null; }
+            else
+            {
+                try {
+                    return new HarmonySerialBlob( bytes );
+                } catch (SQLException se)
+                {
+                    throw StandardException.plainWrapException( se );
+                }
+            }
+        }
+    }
+    
 	/**
 	 * Normalization method - this method may be called when putting
 	 * a value into a SQLBit, for example, when inserting into a SQLBit

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java?rev=982585&r1=982584&r2=982585&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java Thu Aug  5 12:46:51 2010
@@ -559,8 +559,7 @@ public class SQLChar
      */
     public Object   getObject() throws StandardException
     {
-        if ( _clobValue != null ) { return _clobValue; }
-        else { return getString(); }
+        return getString();
     }
 
     /**

Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLClob.java
URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLClob.java?rev=982585&r1=982584&r2=982585&view=diff
==============================================================================
--- db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLClob.java (original)
+++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLClob.java Thu Aug  5 12:46:51 2010
@@ -333,6 +333,21 @@ public class SQLClob
 	}
 
     /**
+     * @exception StandardException     Thrown on error
+     */
+    public Object   getObject() throws StandardException
+    {
+        if ( _clobValue != null ) { return _clobValue; }
+        else
+        {
+            String stringValue = getString();
+
+            if ( stringValue == null ) { return null; }
+            else { return new HarmonySerialClob( stringValue.toCharArray() ); }
+        }
+    }
+
+    /**
      * Returns a descriptor for the input stream for this CLOB value.
      * <p>
      * The descriptor contains information about header data, current positions,