postgresql-jdbc.git / summary / log / commit / refs

commit    82067330ba1d5cdf0bfe1902a16d412f3a08d7d2
Author:   Kris Jurka <books@ejurka.com>
Date:     Sat Jul 17 07:39:43 2004 +0000

    I managed to completely mangle decodeUTF8() in my changes that went into
    build 303. It would incorrectly decode any multibyte UTF8
    representation. Don't know what I was thinking there..
    
    Anyway, here is a patch to repair the damage, and a testcase to check
    that the driver reads/writes unicode strings correctly.
    
    Thanks to Dario Fassi for helping diagnose this.
    
    Oliver Jowett


org/postgresql/core/Encoding.java | 8 +- .../test/jdbc2/DatabaseEncodingTest.java | 100 +++++++++++++++++++++ org/postgresql/test/jdbc2/Jdbc2TestSuite.java | 1 + 3 files changed, 106 insertions(+), 3 deletions(-) diff --git a/org/postgresql/core/Encoding.java b/org/postgresql/core/Encoding.java index 3cf9b607..c019c5d1 100644 --- a/org/postgresql/core/Encoding.java +++ b/org/postgresql/core/Encoding.java @@ -286,11 +286,13 @@ public class Encoding // Length 1: \u00000 .. \u0007f } else if (ch < 0xe0) { // Length 2: \u00080 .. \u007ff - ch = ch | ((data[in++] & 0x7f) << 6); + ch = ((ch & 0x1f) << 6); + ch = ch | (data[in++] & 0x3f); } else { // Length 3: \u00800 .. \u0ffff - ch = ch | ((data[in++] & 0x7f) << 12); - ch = ch | ((data[in++] & 0x7f) << 6); + ch = ((ch & 0x0f) << 12); + ch = ch | ((data[in++] & 0x3f) << 6); + ch = ch | (data[in++] & 0x3f); } cdata[out++] = (char)ch; } diff --git a/org/postgresql/test/jdbc2/DatabaseEncodingTest.java b/org/postgresql/test/jdbc2/DatabaseEncodingTest.java new file mode 100644 index 00000000..bc5eb62c --- /dev/null +++ b/org/postgresql/test/jdbc2/DatabaseEncodingTest.java @@ -0,0 +1,100 @@ +package org.postgresql.test.jdbc2; + +import org.postgresql.test.TestUtil; +import junit.framework.TestCase; +import java.sql.*; + +/* + * Test case for Dario's encoding problems. + */ +public class DatabaseEncodingTest extends TestCase +{ + private Connection con; + + public DatabaseEncodingTest(String name) + { + super(name); + } + + private static final int STEP = 30; + + // Set up the fixture for this testcase: a connection to a database with + // a table for this test. + protected void setUp() throws Exception + { + con = TestUtil.openDB(); + TestUtil.createTable(con, + "testdbencoding", + "unicode_ordinal integer primary key not null, unicode_string varchar(" + STEP + ")"); + } + + // Tear down the fixture for this test case. + protected void tearDown() throws Exception + { + TestUtil.dropTable(con, "testdbencoding"); + TestUtil.closeDB(con); + } + + private static String dumpString(String s) { + StringBuffer sb = new StringBuffer(s.length() * 6); + for (int i = 0; i < s.length(); ++i) { + sb.append("\\u"); + char c = s.charAt(i); + sb.append(Integer.toHexString((c>>12)&15)); + sb.append(Integer.toHexString((c>>8)&15)); + sb.append(Integer.toHexString((c>>4)&15)); + sb.append(Integer.toHexString(c&15)); + } + return sb.toString(); + } + + public void testEncoding() throws Exception { + // Check that we have a UNICODE server encoding, or we must skip this test. + Statement stmt = con.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT getdatabaseencoding()"); + assertTrue(rs.next()); + if (!"UNICODE".equals(rs.getString(1))) { + rs.close(); + return; // not a UNICODE database. + } + + rs.close(); + + con.setAutoCommit(false); // Go faster! + + // Create data. + // NB: we only test up to d800 as code points above that are + // reserved for surrogates in UTF-16 + PreparedStatement insert = con.prepareStatement("INSERT INTO testdbencoding(unicode_ordinal, unicode_string) VALUES (?,?)"); + for (int i = 1; i < 0xd800; i += STEP) { + int count = (i+STEP) > 0xd800 ? 0xd800-i : STEP; + char[] testChars = new char[count]; + for (int j = 0; j < count; ++j) + testChars[j] = (char)(i+j); + + String testString = new String(testChars); + + insert.setInt(1, i); + insert.setString(2, testString); + assertEquals(1, insert.executeUpdate()); + } + + con.commit(); + + // Check data. + rs = stmt.executeQuery("SELECT unicode_ordinal, unicode_string FROM testdbencoding ORDER BY unicode_ordinal"); + for (int i = 1; i < 0xd800; i += STEP) { + assertTrue(rs.next()); + assertEquals(i, rs.getInt(1)); + + int count = (i+STEP) > 0xd800 ? 0xd800-i : STEP; + char[] testChars = new char[count]; + for (int j = 0; j < count; ++j) + testChars[j] = (char)(i+j); + + String testString = new String(testChars); + + assertEquals(dumpString(testString), dumpString(rs.getString(2))); + } + } +} diff --git a/org/postgresql/test/jdbc2/Jdbc2TestSuite.java b/org/postgresql/test/jdbc2/Jdbc2TestSuite.java index cd4af026..7ae92ea2 100644 --- a/org/postgresql/test/jdbc2/Jdbc2TestSuite.java +++ b/org/postgresql/test/jdbc2/Jdbc2TestSuite.java @@ -59,6 +59,7 @@ public class Jdbc2TestSuite extends TestSuite suite.addTestSuite(JBuilderTest.class); suite.addTestSuite(MiscTest.class); suite.addTestSuite(NotifyTest.class); + suite.addTestSuite(DatabaseEncodingTest.class); // Fastpath/LargeObject suite.addTestSuite(BlobTest.class); [parent: 6e294c7dd8fc]