Return-Path: Delivered-To: apmail-db-derby-commits-archive@www.apache.org Received: (qmail 83877 invoked from network); 9 Feb 2009 09:41:29 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 9 Feb 2009 09:41:29 -0000 Received: (qmail 89633 invoked by uid 500); 9 Feb 2009 09:41:29 -0000 Delivered-To: apmail-db-derby-commits-archive@db.apache.org Received: (qmail 89613 invoked by uid 500); 9 Feb 2009 09:41:28 -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 89604 invoked by uid 99); 9 Feb 2009 09:41:28 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Mon, 09 Feb 2009 01:41:28 -0800 X-ASF-Spam-Status: No, hits=-2000.0 required=10.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; Mon, 09 Feb 2009 09:41:28 +0000 Received: by eris.apache.org (Postfix, from userid 65534) id E1382238895D; Mon, 9 Feb 2009 09:41:07 +0000 (UTC) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: svn commit: r742357 - in /db/derby/code/trunk/java: engine/org/apache/derby/iapi/types/SQLChar.java testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CharacterStreamsTest.java Date: Mon, 09 Feb 2009 09:41:07 -0000 To: derby-commits@db.apache.org From: kristwaa@apache.org X-Mailer: svnmailer-1.0.8 Message-Id: <20090209094107.E1382238895D@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org Author: kristwaa Date: Mon Feb 9 09:41:06 2009 New Revision: 742357 URL: http://svn.apache.org/viewvc?rev=742357&view=rev Log: DERBY-4040: SQLChar.getLength returns wrong length for some data values. When asked to return the character length of a SQLChar or SQLVarchar and the value is represented as a stream, skip the two header bytes and then decode the whole stream. The cause of the bug being fixed, was that the byte length was used as the character length. Patch file: derby-4040-1a-SQLChar_length_and_test.diff Modified: db/derby/code/trunk/java/engine/org/apache/derby/iapi/types/SQLChar.java db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CharacterStreamsTest.java 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=742357&r1=742356&r2=742357&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 Mon Feb 9 09:41:06 2009 @@ -44,6 +44,7 @@ import org.apache.derby.iapi.services.cache.ClassSize; import org.apache.derby.iapi.services.io.ArrayInputStream; +import org.apache.derby.iapi.services.io.InputStreamUtil; import org.apache.derby.iapi.util.StringUtil; import org.apache.derby.iapi.util.UTF8Util; import org.apache.derby.iapi.services.i18n.LocaleFinder; @@ -589,18 +590,10 @@ if (stream != null) { if (stream instanceof Resetable && stream instanceof ObjectInput) { try { - int clobLength = 0; - // If we have the stream length encoded. - // just read that. - int utf8len = readCharacterLength((ObjectInput) stream); - if (utf8len != 0) { - clobLength = utf8len; - return clobLength; - } - // Otherwise we will have to read the whole stream. - int skippedCharSize = (int) UTF8Util.skipUntilEOF(stream); - clobLength = skippedCharSize; - return clobLength; + // Skip the encoded byte length. + InputStreamUtil.skipFully(stream, 2); + // Decode the whole stream to find the character length. + return (int)UTF8Util.skipUntilEOF(stream); } catch (IOException ioe) { throwStreamingIOException(ioe); } finally { Modified: db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CharacterStreamsTest.java URL: http://svn.apache.org/viewvc/db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CharacterStreamsTest.java?rev=742357&r1=742356&r2=742357&view=diff ============================================================================== --- db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CharacterStreamsTest.java (original) +++ db/derby/code/trunk/java/testing/org/apache/derbyTesting/functionTests/tests/jdbcapi/CharacterStreamsTest.java Mon Feb 9 09:41:06 2009 @@ -29,6 +29,8 @@ import java.sql.SQLException; import java.sql.Statement; import junit.framework.Test; +import org.apache.derbyTesting.functionTests.util.streams.CharAlphabet; +import org.apache.derbyTesting.functionTests.util.streams.LoopingAlphabetReader; import org.apache.derbyTesting.junit.BaseJDBCTestCase; import org.apache.derbyTesting.junit.TestConfiguration; @@ -219,14 +221,23 @@ "insert into charstream(c, vc, lvc, lob) " + "values(?,?,?,?)"); PreparedStatement psDel = prepareStatement("DELETE FROM charstream"); + PreparedStatement psqSQLLength = prepareStatement( + "select length(c), length(vc), length(lvc), length(lob) " + + "from charstream"); PreparedStatement psq2 = prepareStatement("select c, vc, lvc, lob from charstream"); println("setCharacterStream(LONG CHARACTER STREAMS WITH UNICODE)"); - checkCharacterStreams(psDel, psi, psq2, 14, 93, 55, 55); - checkCharacterStreams(psDel, psi, psq2, 25, 19332, 18733, 18733); - checkCharacterStreams(psDel, psi, psq2, 1, 32433, 32673, 32673); - checkCharacterStreams(psDel, psi, psq2, 0, 32532, 32700, 32700); + checkCharacterStreams( + psDel, psi, psq2, psqSQLLength, 14, 93, 55, 55, 0); + checkCharacterStreams( + psDel, psi, psq2, psqSQLLength, 21, 10887, 10887, 10887, 3); + checkCharacterStreams( + psDel, psi, psq2, psqSQLLength, 25, 19332, 18733, 18733, 0); + checkCharacterStreams( + psDel, psi, psq2, psqSQLLength, 1, 32433, 32673, 32673, 0); + checkCharacterStreams( + psDel, psi, psq2, psqSQLLength, 0, 32532, 32700, 32700, 0); psi.close(); psDel.close(); @@ -555,34 +566,64 @@ rs.close(); } + private Reader getSourceStream(int length, int bytesPerChar) { + switch (bytesPerChar) { + case 0: + return new c3Reader(length); + case 1: + return new LoopingAlphabetReader(length, + CharAlphabet.modernLatinLowercase()); + case 2: + return new LoopingAlphabetReader(length, + CharAlphabet.tamil()); + case 3: + return new LoopingAlphabetReader(length, + CharAlphabet.cjkSubset()); + default: + fail("Illegal value of bytesPerChar: " + bytesPerChar); + return null; + } + } + private void checkCharacterStreams( PreparedStatement psDel, PreparedStatement psi, PreparedStatement psq2, - int cl, int vcl, int lvcl, int lob) + PreparedStatement psqSQLLength, + int cl, int vcl, int lvcl, int lob, + int bytesPerChar) throws SQLException, IOException { psDel.executeUpdate(); - psi.setCharacterStream(1, new c3Reader(cl), cl); - psi.setCharacterStream(2, new c3Reader(vcl), vcl); - psi.setCharacterStream(3, new c3Reader(lvcl), lvcl); - psi.setCharacterStream(4, new c3Reader(lob), lob); + psi.setCharacterStream(1, getSourceStream(cl, bytesPerChar), cl); + psi.setCharacterStream(2, getSourceStream(vcl, bytesPerChar), vcl); + psi.setCharacterStream(3, getSourceStream(lvcl, bytesPerChar), lvcl); + psi.setCharacterStream(4, getSourceStream(lob, bytesPerChar), lob); psi.executeUpdate(); + ResultSet rsLength = psqSQLLength.executeQuery(); + assertTrue(rsLength.next()); + assertEquals(25, rsLength.getInt(1)); // CHAR + assertEquals(vcl, rsLength.getInt(2)); // VARCHAR + assertEquals(lvcl, rsLength.getInt(3)); // LONG VARCHAR + assertEquals(lob, rsLength.getInt(4)); //CLOB + assertFalse(rsLength.next()); + rsLength.close(); + ResultSet rs = psq2.executeQuery(); rs.next(); InputStream is = rs.getAsciiStream(1); - checkCharStream(is, cl, 25); + checkCharStream(is, cl, 25, bytesPerChar); is = rs.getAsciiStream(2); - checkCharStream(is, vcl, -1); + checkCharStream(is, vcl, -1, bytesPerChar); is = rs.getAsciiStream(3); - checkCharStream(is, lvcl, -1); + checkCharStream(is, lvcl, -1, bytesPerChar); is = rs.getAsciiStream(4); - checkCharStream(is, lob, -1); + checkCharStream(is, lob, -1, bytesPerChar); rs.close(); @@ -590,16 +631,16 @@ rs.next(); Reader r = rs.getCharacterStream(1); - checkCharStream(r, cl, 25); + checkCharStream(r, cl, 25, bytesPerChar); r = rs.getCharacterStream(2); - checkCharStream(r, vcl, -1); + checkCharStream(r, vcl, -1, bytesPerChar); r = rs.getCharacterStream(3); - checkCharStream(r, lvcl, -1); + checkCharStream(r, lvcl, -1, bytesPerChar); r = rs.getCharacterStream(4); - checkCharStream(r, lob, -1); + checkCharStream(r, lob, -1, bytesPerChar); rs.close(); @@ -609,19 +650,19 @@ String suv = rs.getString(1); r = new StringReader(suv); - checkCharStream(r, cl, 25); + checkCharStream(r, cl, 25, bytesPerChar); suv = rs.getString(2); r = new StringReader(suv); - checkCharStream(r, vcl, -1); + checkCharStream(r, vcl, -1, bytesPerChar); suv = rs.getString(3); r = new StringReader(suv); - checkCharStream(r, lvcl, -1); + checkCharStream(r, lvcl, -1, bytesPerChar); suv = rs.getString(4); r = new StringReader(suv); - checkCharStream(r, lob, -1); + checkCharStream(r, lob, -1, bytesPerChar); rs.close(); @@ -703,11 +744,12 @@ r.close(); } - private void checkCharStream(InputStream is, int length, int fixedLen) + private void checkCharStream(InputStream is, int length, int fixedLen, + int bytesPerChar) throws IOException { - Reader orig = new c3Reader(length); + Reader orig = getSourceStream(length, bytesPerChar); int count = 0; for (;;) { @@ -748,11 +790,12 @@ is.close(); } - private void checkCharStream(Reader r, int length, int fixedLen) + private void checkCharStream(Reader r, int length, int fixedLen, + int bytesPerChar) throws IOException { - Reader orig = new c3Reader(length); + Reader orig = getSourceStream(length, bytesPerChar); int count = 0; for (;;) {