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
MemoryPool Interface for managing MemoryPools. Not used (yet).
ObjectPool Interface for an Object Pool
SimpleObjectPool Class that implements ObjectPool and used by BytePoolDim#
Encoding Character encoding logic, mainly for Connection and PG_Stream.
Package org.postgresql.fastpath
---------------------------
......
......@@ -10,7 +10,7 @@ import org.postgresql.core.*;
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
* backend.
......@@ -208,7 +208,7 @@ public class PG_Stream
* @return string from back end
* @exception SQLException if an I/O error occurs, or end of file
*/
public String ReceiveString(String encoding)
public String ReceiveString(Encoding encoding)
throws SQLException
{
int s = 0;
......@@ -239,18 +239,7 @@ public class PG_Stream
} catch (IOException e) {
throw new PSQLException("postgresql.stream.ioerror",e);
}
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;
return encoding.decode(rst, 0, s);
}
/**
......
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.*;
import org.postgresql.Field;
import org.postgresql.largeobject.*;
import org.postgresql.util.*;
import org.postgresql.core.Encoding;
/**
* 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
*/
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)
throw new PSQLException("postgresql.res.colrange");
wasNullFlag = (this_row[columnIndex - 1] == null);
if(wasNullFlag)
return null;
String encoding = connection.getEncoding();
if (encoding == null)
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);
}
}
Encoding encoding = connection.getEncoding();
return encoding.decode(this_row[columnIndex - 1]);
}
/**
......
......@@ -5,7 +5,6 @@ package org.postgresql.jdbc2;
// changes are also made (if relevent) to the related JDBC 1 class in the
// org.postgresql.jdbc1 package.
import java.lang.*;
import java.io.*;
import java.math.*;
......@@ -15,6 +14,7 @@ import java.sql.*;
import org.postgresql.Field;
import org.postgresql.largeobject.*;
import org.postgresql.util.*;
import org.postgresql.core.Encoding;
/**
* 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
if(wasNullFlag)
return null;
String encoding = connection.getEncoding();
if (encoding == null)
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);
}
}
Encoding encoding = connection.getEncoding();
return encoding.decode(this_row[columnIndex - 1]);
}
/**
......@@ -1006,15 +998,9 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
public java.io.Reader getCharacterStream(int i) throws SQLException
{
// New in 7.1
try {
String encoding = connection.getEncoding();
if(encoding==null)
return new InputStreamReader(getBinaryStream(i));
return new InputStreamReader(getBinaryStream(i),encoding);
} catch (UnsupportedEncodingException unse) {
throw new PSQLException("postgresql.res.encoding", unse);
}
Encoding encoding = connection.getEncoding();
InputStream input = getBinaryStream(i);
return encoding.getDecodingReader(input);
}
/**
......
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 {
suite.addTestSuite(DriverTest.class);
suite.addTestSuite(ConnectionTest.class);
suite.addTestSuite(DatabaseMetaDataTest.class);
suite.addTestSuite(EncodingTest.class);
// 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