From derby-commits-return-14619-apmail-db-derby-commits-archive=db.apache.org@db.apache.org Tue Jul 5 05:58:49 2011 Return-Path: X-Original-To: apmail-db-derby-commits-archive@www.apache.org Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: from mail.apache.org (hermes.apache.org [140.211.11.3]) by minotaur.apache.org (Postfix) with SMTP id B2E224FAD for ; Tue, 5 Jul 2011 05:58:49 +0000 (UTC) Received: (qmail 81643 invoked by uid 500); 5 Jul 2011 05:58:49 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 81565 invoked by uid 500); 5 Jul 2011 05:58:42 -0000 Mailing-List: contact derby-commits-help@db.apache.org; run by ezmlm Precedence: bulk list-help: list-unsubscribe: List-Post: Reply-To: "Derby Development" List-Id: Delivered-To: mailing list derby-commits@db.apache.org Received: (qmail 81550 invoked by uid 99); 5 Jul 2011 05:58:40 -0000 Received: from nike.apache.org (HELO nike.apache.org) (192.87.106.230) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 05 Jul 2011 05:58:40 +0000 X-ASF-Spam-Status: No, hits=-2000.0 required=5.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO eris.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 05 Jul 2011 05:58:36 +0000 Received: from eris.apache.org (localhost [127.0.0.1]) by eris.apache.org (Postfix) with ESMTP id 2BC8423889E1; Tue, 5 Jul 2011 05:58:14 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r1142896 - in /db/derby/code/trunk/java: client/org/apache/derby/client/am/ engine/org/apache/derby/iapi/services/io/ engine/org/apache/derby/impl/jdbc/ Date: Tue, 05 Jul 2011 05:58:14 -0000 To: derby-commits@db.apache.org From: kristwaa@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20110705055814.2BC8423889E1@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: kristwaa Date: Tue Jul 5 05:58:13 2011 New Revision: 1142896 URL: http://svn.apache.org/viewvc?rev=1142896&view=rev Log: DERBY-5090: Retrieving BLOB fields sometimes fails Make Derby close open streams obtained from the result set when the next get-call is invoked (as dictated by JDBC standard). This was done for some streams, but not all. What happened was also different for the client and the embedded driver. Added CloseFilterInputStream (modeled after existing class in the client). Removed NewByteArrayInputStream, used Java API class instead. Patch file: derby-5090-1b-fix.diff Added: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/CloseFilterInputStream.java (with props) Removed: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/NewByteArrayInputStream.java Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/AccessibleByteArrayOutputStream.java db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java Modified: db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java?rev=1142896&r1=1142895&r2=1142896&view=diff ============================================================================== --- db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java (original) +++ db/derby/code/trunk/java/client/org/apache/derby/client/am/ResultSet.java Tue Jul 5 05:58:13 2011 @@ -30,7 +30,6 @@ import java.sql.Time; import java.sql.Timestamp; import java.util.Arrays; import java.util.Calendar; -import org.apache.derby.client.am.SQLExceptionFactory; import org.apache.derby.shared.common.reference.SQLState; import org.apache.derby.shared.common.sanity.SanityManager; @@ -49,7 +48,8 @@ public abstract class ResultSet implemen public Section generatedSection_ = null; - private CloseFilterInputStream is_; + private CloseFilterInputStream currentStream; + private Reader currentReader; //---------------------navigational cheat-links------------------------------- // Cheat-links are for convenience only, and are not part of the conceptual model. @@ -439,7 +439,7 @@ public abstract class ResultSet implemen if (!openOnClient_) { return; } - closeCloseFilterInputStream(); + closeOpenStreams(); // See if there are open locators on the current row, if valid. if (isValidCursorPosition_ && !isOnInsertRow_) { lobState.checkCurrentRow(cursor_); @@ -576,7 +576,7 @@ public abstract class ResultSet implemen public boolean getBoolean(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getBoolean", column); @@ -610,7 +610,7 @@ public abstract class ResultSet implemen public byte getByte(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getByte", column); @@ -644,7 +644,7 @@ public abstract class ResultSet implemen public short getShort(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getShort", column); @@ -678,7 +678,7 @@ public abstract class ResultSet implemen public int getInt(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getInt", column); @@ -712,7 +712,7 @@ public abstract class ResultSet implemen public long getLong(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getLong", column); @@ -746,7 +746,7 @@ public abstract class ResultSet implemen public float getFloat(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getFloat", column); @@ -780,7 +780,7 @@ public abstract class ResultSet implemen public double getDouble(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getDouble", column); @@ -815,7 +815,7 @@ public abstract class ResultSet implemen public java.math.BigDecimal getBigDecimal(int column, int scale) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceDeprecatedEntry(this, "getBigDecimal", column, scale); @@ -847,7 +847,7 @@ public abstract class ResultSet implemen try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getBigDecimal", column); @@ -877,7 +877,7 @@ public abstract class ResultSet implemen public java.sql.Date getDate(int column, Calendar cal) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getDate", column); @@ -920,7 +920,7 @@ public abstract class ResultSet implemen public java.sql.Time getTime(int column, Calendar cal) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getTime", column, cal); @@ -964,7 +964,7 @@ public abstract class ResultSet implemen throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry( @@ -1056,7 +1056,7 @@ public abstract class ResultSet implemen public String getString(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getString", column); @@ -1084,7 +1084,7 @@ public abstract class ResultSet implemen public byte[] getBytes(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getBytes", column); @@ -1112,7 +1112,7 @@ public abstract class ResultSet implemen public java.io.InputStream getBinaryStream(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getBinaryStream", column); @@ -1143,7 +1143,7 @@ public abstract class ResultSet implemen public java.io.InputStream getAsciiStream(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getAsciiStream", column); @@ -1194,7 +1194,7 @@ public abstract class ResultSet implemen public java.io.Reader getCharacterStream(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getCharacterStream", column); @@ -1214,6 +1214,7 @@ public abstract class ResultSet implemen agent_.logWriter_.traceExit(this, "getCharacterStream", result); } setWasNull(column); // Placed close to the return to minimize risk of thread interference + currentReader = result; return result; } catch ( SqlException se ) @@ -1226,7 +1227,7 @@ public abstract class ResultSet implemen public java.sql.Blob getBlob(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getBlob", column); @@ -1256,7 +1257,7 @@ public abstract class ResultSet implemen public java.sql.Clob getClob(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getClob", column); @@ -1286,7 +1287,7 @@ public abstract class ResultSet implemen public java.sql.Ref getRef(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getRef", column); @@ -1313,7 +1314,7 @@ public abstract class ResultSet implemen public java.sql.Array getArray(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getArray", column); @@ -1340,7 +1341,7 @@ public abstract class ResultSet implemen public Object getObject(int column) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getObject", column); @@ -1374,7 +1375,7 @@ public abstract class ResultSet implemen public Object getObject(int column, java.util.Map map) throws SQLException { try { - closeCloseFilterInputStream(); + closeOpenStreams(); if (agent_.loggingEnabled()) { agent_.logWriter_.traceEntry(this, "getObject", column, map); @@ -5433,35 +5434,50 @@ public abstract class ResultSet implemen return null; } - if( is_ == is ){ - return is_; + if( currentStream == is ){ + return currentStream; } - closeCloseFilterInputStream(); + closeOpenStreams(); - is_ = new CloseFilterInputStream(is); + currentStream = new CloseFilterInputStream(is); - return is_; + return currentStream; } - private void closeCloseFilterInputStream() throws SqlException { - - if(is_ != null){ - try{ - is_.close(); - - }catch(IOException e){ - throw new SqlException(agent_.logWriter_ , - new ClientMessageId(SQLState.JAVA_EXCEPTION), - "java.io.IOException", e.getMessage(), e); - } - - is_ = null; - - } - } + /** + * Closes the current stream, if there is one. + *

+ * Note that streams are implicitly closed when the next value is fetched. + * + * @throws SqlException if closing the stream fails + */ + private void closeOpenStreams() throws SqlException { + // There will be zero or one stream to close (both cannot be current). + if (currentStream != null) { + try { + currentStream.close(); + } catch (IOException ioe) { + throw new SqlException(agent_.logWriter_, + new ClientMessageId(SQLState.JAVA_EXCEPTION), + "java.io.IOException", ioe.getMessage(), ioe); + } + currentStream = null; + } + + if (currentReader != null) { + try { + currentReader.close(); + } catch (IOException ioe) { + throw new SqlException(agent_.logWriter_, + new ClientMessageId(SQLState.JAVA_EXCEPTION), + "java.io.IOException", ioe.getMessage(), ioe); + } + currentReader = null; + } + } /** Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/AccessibleByteArrayOutputStream.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/AccessibleByteArrayOutputStream.java?rev=1142896&r1=1142895&r2=1142896&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/AccessibleByteArrayOutputStream.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/AccessibleByteArrayOutputStream.java Tue Jul 5 05:58:13 2011 @@ -21,6 +21,7 @@ package org.apache.derby.iapi.services.io; +import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -83,7 +84,7 @@ public class AccessibleByteArrayOutputSt */ public InputStream getInputStream() { - return new NewByteArrayInputStream(buf, 0, count); + return new ByteArrayInputStream(buf, 0, count); } /** Added: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/CloseFilterInputStream.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/CloseFilterInputStream.java?rev=1142896&view=auto ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/CloseFilterInputStream.java (added) +++ db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/CloseFilterInputStream.java Tue Jul 5 05:58:13 2011 @@ -0,0 +1,84 @@ +/* + + Derby - Class org.apache.derby.iapi.services.io.CloseFilterInputStream + + 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.services.io; + +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.apache.derby.iapi.reference.MessageId; +import org.apache.derby.iapi.services.i18n.MessageService; + +/** + * A stream that will throw an exception if its methods are invoked after it + * has been closed. + */ +public class CloseFilterInputStream + extends FilterInputStream { + + /** Message, modeled after CloseFilterInputStream in the client. */ + private static final String MESSAGE = + MessageService.getTextMessage(MessageId.CONN_ALREADY_CLOSED); + + /** Tells if this stream has been closed. */ + private boolean closed; + + public CloseFilterInputStream(InputStream in) { + super(in); + } + + public void close() throws IOException { + closed = true; + super.close(); + } + + public int available() throws IOException { + checkIfClosed(); + return super.available(); + } + + public int read() throws IOException { + checkIfClosed(); + return super.read(); + } + + public int read(byte[] b) throws IOException { + checkIfClosed(); + return super.read(b); + } + + public int read(byte[] b, int off, int len) throws IOException { + checkIfClosed(); + return super.read(b, off, len); + } + + public long skip(long n) throws IOException { + checkIfClosed(); + return super.skip(n); + } + + /** Throws exception if this stream has been closed. */ + private void checkIfClosed() throws IOException { + if (closed) { + throw new IOException(MESSAGE); + } + } +} Propchange: db/derby/code/trunk/java/engine/org/apache/derby/iapi/services/io/CloseFilterInputStream.java ------------------------------------------------------------------------------ svn:eol-style = native Modified: db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java?rev=1142896&r1=1142895&r2=1142896&view=diff ============================================================================== --- db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java (original) +++ db/derby/code/trunk/java/engine/org/apache/derby/impl/jdbc/EmbedResultSet.java Tue Jul 5 05:58:13 2011 @@ -21,6 +21,8 @@ package org.apache.derby.impl.jdbc; +import java.io.ByteArrayInputStream; + import org.apache.derby.iapi.services.sanity.SanityManager; import org.apache.derby.iapi.error.StandardException; @@ -50,7 +52,6 @@ import org.apache.derby.iapi.sql.ResultD import org.apache.derby.iapi.services.io.StreamStorable; import org.apache.derby.iapi.services.io.LimitInputStream; -import org.apache.derby.iapi.services.io.NewByteArrayInputStream; import org.apache.derby.iapi.error.ExceptionSeverity; import org.apache.derby.iapi.reference.SQLState; @@ -77,6 +78,7 @@ import java.util.Arrays; import java.util.Calendar; import org.apache.derby.iapi.jdbc.CharacterStreamDescriptor; +import org.apache.derby.iapi.services.io.CloseFilterInputStream; import org.apache.derby.iapi.sql.dictionary.DataDictionary; import org.apache.derby.iapi.types.StringDataValue; import org.apache.derby.iapi.util.IdUtil; @@ -1271,7 +1273,7 @@ public abstract class EmbedResultSet ext if (dvd.hasStream()) { stream = new BinaryToRawStream(dvd.getStream(), dvd); } else { - stream = new NewByteArrayInputStream(dvd.getBytes()); + stream = new ByteArrayInputStream(dvd.getBytes()); } if (lmfs > 0) @@ -1281,7 +1283,9 @@ public abstract class EmbedResultSet ext limitResultIn.setLimit(lmfs); stream = limitResultIn; } - currentStream = stream; + // Wrap in a stream throwing exception on invocations when closed. + stream = new CloseFilterInputStream(stream); + currentStream = stream; return stream; } catch (Throwable t) {