Commit ff21a8e5 authored by Bruce Momjian's avatar Bruce Momjian

JDBC encoding additions.

Here's a patch against the current CVS. The changes from the previous
patch are mostly related to the changed interface for PG_Stream.

Anders Bengtsson
parent 12f59470
...@@ -151,6 +151,7 @@ BytePoolDim2 Handles a pool of byte[][] arrays ...@@ -151,6 +151,7 @@ BytePoolDim2 Handles a pool of byte[][] arrays
MemoryPool Interface for managing MemoryPools. Not used (yet). MemoryPool Interface for managing MemoryPools. Not used (yet).
ObjectPool Interface for an Object Pool ObjectPool Interface for an Object Pool
SimpleObjectPool Class that implements ObjectPool and used by BytePoolDim# SimpleObjectPool Class that implements ObjectPool and used by BytePoolDim#
Encoding Character encoding logic, mainly for Connection and PG_Stream.
Package org.postgresql.fastpath Package org.postgresql.fastpath
--------------------------- ---------------------------
......
...@@ -10,7 +10,7 @@ import org.postgresql.core.*; ...@@ -10,7 +10,7 @@ import org.postgresql.core.*;
import org.postgresql.util.*; import org.postgresql.util.*;
/** /**
* @version 1.0 15-APR-1997 * $Id: PG_Stream.java,v 1.10 2001/07/21 18:52:10 momjian Exp $
* *
* This class is used by Connection & PGlobj for communicating with the * This class is used by Connection & PGlobj for communicating with the
* backend. * backend.
...@@ -208,7 +208,7 @@ public class PG_Stream ...@@ -208,7 +208,7 @@ public class PG_Stream
* @return string from back end * @return string from back end
* @exception SQLException if an I/O error occurs, or end of file * @exception SQLException if an I/O error occurs, or end of file
*/ */
public String ReceiveString(String encoding) public String ReceiveString(Encoding encoding)
throws SQLException throws SQLException
{ {
int s = 0; int s = 0;
...@@ -239,18 +239,7 @@ public class PG_Stream ...@@ -239,18 +239,7 @@ public class PG_Stream
} catch (IOException e) { } catch (IOException e) {
throw new PSQLException("postgresql.stream.ioerror",e); throw new PSQLException("postgresql.stream.ioerror",e);
} }
return encoding.decode(rst, 0, s);
String v = null;
if (encoding == null)
v = new String(rst, 0, s);
else {
try {
v = new String(rst, 0, s, encoding);
} catch (UnsupportedEncodingException unse) {
throw new PSQLException("postgresql.stream.encoding", unse);
}
}
return v;
} }
/** /**
......
package org.postgresql.core;
import java.io.*;
import java.util.*;
import java.sql.SQLException;
import org.postgresql.util.*;
/**
* Converts to and from the character encoding used by the backend.
*
* $Id: Encoding.java,v 1.1 2001/07/21 18:52:11 momjian Exp $
*/
public class Encoding {
private static final Encoding DEFAULT_ENCODING = new Encoding(null);
/**
* Preferred JVM encodings for backend encodings.
*/
private static final Hashtable encodings = new Hashtable();
static {
encodings.put("SQL_ASCII", new String[] { "ASCII", "us-ascii" });
encodings.put("UNICODE", new String[] { "UTF-8", "UTF8" });
encodings.put("LATIN1", new String[] { "ISO8859_1" });
encodings.put("LATIN2", new String[] { "ISO8859_2" });
encodings.put("LATIN3", new String[] { "ISO8859_3" });
encodings.put("LATIN4", new String[] { "ISO8859_4" });
encodings.put("LATIN5", new String[] { "ISO8859_5" });
encodings.put("LATIN6", new String[] { "ISO8859_6" });
encodings.put("LATIN7", new String[] { "ISO8859_7" });
encodings.put("LATIN8", new String[] { "ISO8859_8" });
encodings.put("LATIN9", new String[] { "ISO8859_9" });
encodings.put("EUC_JP", new String[] { "EUC_JP" });
encodings.put("EUC_CN", new String[] { "EUC_CN" });
encodings.put("EUC_KR", new String[] { "EUC_KR" });
encodings.put("EUC_TW", new String[] { "EUC_TW" });
encodings.put("WIN", new String[] { "Cp1252" });
// We prefer KOI8-U, since it is a superset of KOI8-R.
encodings.put("KOI8", new String[] { "KOI8_U", "KOI8_R" });
// If the database isn't encoding-aware then we can't have
// any preferred encodings.
encodings.put("UNKNOWN", new String[0]);
}
private final String encoding;
private Encoding(String encoding) {
this.encoding = encoding;
}
/**
* Get an Encoding for from the given database encoding and
* the encoding passed in by the user.
*/
public static Encoding getEncoding(String databaseEncoding,
String passedEncoding)
{
if (passedEncoding != null) {
if (isAvailable(passedEncoding)) {
return new Encoding(passedEncoding);
} else {
return defaultEncoding();
}
} else {
return encodingForDatabaseEncoding(databaseEncoding);
}
}
/**
* Get an Encoding matching the given database encoding.
*/
private static Encoding encodingForDatabaseEncoding(String databaseEncoding) {
// If the backend encoding is known and there is a suitable
// encoding in the JVM we use that. Otherwise we fall back
// to the default encoding of the JVM.
if (encodings.containsKey(databaseEncoding)) {
String[] candidates = (String[]) encodings.get(databaseEncoding);
for (int i = 0; i < candidates.length; i++) {
if (isAvailable(candidates[i])) {
return new Encoding(candidates[i]);
}
}
}
return defaultEncoding();
}
/**
* Name of the (JVM) encoding used.
*/
public String name() {
return encoding;
}
/**
* Encode a string to an array of bytes.
*/
public byte[] encode(String s) throws SQLException {
try {
if (encoding == null) {
return s.getBytes();
} else {
return s.getBytes(encoding);
}
} catch (UnsupportedEncodingException e) {
throw new PSQLException("postgresql.stream.encoding", e);
}
}
/**
* Decode an array of bytes into a string.
*/
public String decode(byte[] encodedString, int offset, int length) throws SQLException {
try {
if (encoding == null) {
return new String(encodedString, offset, length);
} else {
return new String(encodedString, offset, length, encoding);
}
} catch (UnsupportedEncodingException e) {
throw new PSQLException("postgresql.stream.encoding", e);
}
}
/**
* Decode an array of bytes into a string.
*/
public String decode(byte[] encodedString) throws SQLException {
return decode(encodedString, 0, encodedString.length);
}
/**
* Get a Reader that decodes the given InputStream.
*/
public Reader getDecodingReader(InputStream in) throws SQLException {
try {
if (encoding == null) {
return new InputStreamReader(in);
} else {
return new InputStreamReader(in, encoding);
}
} catch (UnsupportedEncodingException e) {
throw new PSQLException("postgresql.res.encoding", e);
}
}
/**
* Get an Encoding using the default encoding for the JVM.
*/
public static Encoding defaultEncoding() {
return DEFAULT_ENCODING;
}
/**
* Test if an encoding is available in the JVM.
*/
private static boolean isAvailable(String encodingName) {
try {
"DUMMY".getBytes(encodingName);
return true;
} catch (UnsupportedEncodingException e) {
return false;
}
}
}
...@@ -14,6 +14,7 @@ import java.sql.*; ...@@ -14,6 +14,7 @@ import java.sql.*;
import org.postgresql.Field; import org.postgresql.Field;
import org.postgresql.largeobject.*; import org.postgresql.largeobject.*;
import org.postgresql.util.*; import org.postgresql.util.*;
import org.postgresql.core.Encoding;
/** /**
* A ResultSet provides access to a table of data generated by executing a * A ResultSet provides access to a table of data generated by executing a
...@@ -154,26 +155,15 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu ...@@ -154,26 +155,15 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
*/ */
public String getString(int columnIndex) throws SQLException public String getString(int columnIndex) throws SQLException
{ {
//byte[] bytes = getBytes(columnIndex);
//
//if (bytes == null)
//return null;
//return new String(bytes);
if (columnIndex < 1 || columnIndex > fields.length) if (columnIndex < 1 || columnIndex > fields.length)
throw new PSQLException("postgresql.res.colrange"); throw new PSQLException("postgresql.res.colrange");
wasNullFlag = (this_row[columnIndex - 1] == null); wasNullFlag = (this_row[columnIndex - 1] == null);
if(wasNullFlag) if(wasNullFlag)
return null; return null;
String encoding = connection.getEncoding();
if (encoding == null) Encoding encoding = connection.getEncoding();
return new String(this_row[columnIndex - 1]); return encoding.decode(this_row[columnIndex - 1]);
else {
try {
return new String(this_row[columnIndex - 1], encoding);
} catch (UnsupportedEncodingException unse) {
throw new PSQLException("postgresql.res.encoding", unse);
}
}
} }
/** /**
......
...@@ -5,7 +5,6 @@ package org.postgresql.jdbc2; ...@@ -5,7 +5,6 @@ package org.postgresql.jdbc2;
// changes are also made (if relevent) to the related JDBC 1 class in the // changes are also made (if relevent) to the related JDBC 1 class in the
// org.postgresql.jdbc1 package. // org.postgresql.jdbc1 package.
import java.lang.*; import java.lang.*;
import java.io.*; import java.io.*;
import java.math.*; import java.math.*;
...@@ -15,6 +14,7 @@ import java.sql.*; ...@@ -15,6 +14,7 @@ import java.sql.*;
import org.postgresql.Field; import org.postgresql.Field;
import org.postgresql.largeobject.*; import org.postgresql.largeobject.*;
import org.postgresql.util.*; import org.postgresql.util.*;
import org.postgresql.core.Encoding;
/** /**
* A ResultSet provides access to a table of data generated by executing a * A ResultSet provides access to a table of data generated by executing a
...@@ -172,16 +172,8 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu ...@@ -172,16 +172,8 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
if(wasNullFlag) if(wasNullFlag)
return null; return null;
String encoding = connection.getEncoding(); Encoding encoding = connection.getEncoding();
if (encoding == null) return encoding.decode(this_row[columnIndex - 1]);
return new String(this_row[columnIndex - 1]);
else {
try {
return new String(this_row[columnIndex - 1], encoding);
} catch (UnsupportedEncodingException unse) {
throw new PSQLException("postgresql.res.encoding", unse);
}
}
} }
/** /**
...@@ -1006,15 +998,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu ...@@ -1006,15 +998,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
public java.io.Reader getCharacterStream(int i) throws SQLException public java.io.Reader getCharacterStream(int i) throws SQLException
{ {
// New in 7.1 Encoding encoding = connection.getEncoding();
try { InputStream input = getBinaryStream(i);
String encoding = connection.getEncoding(); return encoding.getDecodingReader(input);
if(encoding==null)
return new InputStreamReader(getBinaryStream(i));
return new InputStreamReader(getBinaryStream(i),encoding);
} catch (UnsupportedEncodingException unse) {
throw new PSQLException("postgresql.res.encoding", unse);
}
} }
/** /**
......
package org.postgresql.test.jdbc2;
import junit.framework.*;
import org.postgresql.core.Encoding;
import java.io.*;
/**
* Tests for the Encoding class.
*
* $Id: EncodingTest.java,v 1.1 2001/07/21 18:52:11 momjian Exp $
*/
public class EncodingTest extends TestCase {
public EncodingTest(String name) {
super(name);
}
public void testCreation() throws Exception {
Encoding encoding;
encoding = Encoding.getEncoding("UNICODE", null);
assertEquals("UTF", encoding.name().substring(0, 3).toUpperCase());
encoding = Encoding.getEncoding("SQL_ASCII", null);
assert(encoding.name().toUpperCase().indexOf("ASCII") != -1);
assertEquals("When encoding is unknown the default encoding should be used",
Encoding.defaultEncoding(),
Encoding.getEncoding("UNKNOWN", null));
encoding = Encoding.getEncoding("SQL_ASCII", "utf-8");
assert("Encoding passed in by the user should be preferred",
encoding.name().toUpperCase().indexOf("UTF") != -1);
}
public void testTransformations() throws Exception {
Encoding encoding = Encoding.getEncoding("UNICODE", null);
assertEquals("ab", encoding.decode(new byte[] { 97, 98 }));
assertEquals(2, encoding.encode("ab").length);
assertEquals(97, encoding.encode("a")[0]);
assertEquals(98, encoding.encode("b")[0]);
encoding = Encoding.defaultEncoding();
assertEquals("a".getBytes()[0], encoding.encode("a")[0]);
assertEquals(new String(new byte[] { 97 }),
encoding.decode(new byte[] { 97 }));
}
public void testReader() throws Exception {
Encoding encoding = Encoding.getEncoding("SQL_ASCII", null);
InputStream stream = new ByteArrayInputStream(new byte[] { 97, 98 });
Reader reader = encoding.getDecodingReader(stream);
assertEquals(97, reader.read());
assertEquals(98, reader.read());
assertEquals(-1, reader.read());
}
}
...@@ -195,6 +195,7 @@ public class JDBC2Tests extends TestSuite { ...@@ -195,6 +195,7 @@ public class JDBC2Tests extends TestSuite {
suite.addTestSuite(DriverTest.class); suite.addTestSuite(DriverTest.class);
suite.addTestSuite(ConnectionTest.class); suite.addTestSuite(ConnectionTest.class);
suite.addTestSuite(DatabaseMetaDataTest.class); suite.addTestSuite(DatabaseMetaDataTest.class);
suite.addTestSuite(EncodingTest.class);
// Connectivity/Protocols // Connectivity/Protocols
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment