On Sun, 15 Jul 2001, Bruce Momjian wrote:

> I am having trouble applying this patch to the current CVS tree.  The
> majority of changes fail to apply.  Can you give me a patch against
> current CVS or can someone manually merge the changes into CVS and send
> me a patch?  Thanks.

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
_____________________________________________________________________
A n d e r s  B e n g t s s o n                   [EMAIL PROTECTED]
Stockholm, Sweden
Index: src/interfaces/jdbc/Implementation
===================================================================
RCS file: /home/projects/pgsql/cvsroot/pgsql/src/interfaces/jdbc/Implementation,v
retrieving revision 1.2
diff -c -r1.2 Implementation
*** src/interfaces/jdbc/Implementation  2001/01/18 14:50:14     1.2
--- src/interfaces/jdbc/Implementation  2001/07/19 14:17:49
***************
*** 151,156 ****
--- 151,157 ----
  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
  ---------------------------
Index: src/interfaces/jdbc/org/postgresql/Connection.java
===================================================================
RCS file: 
/home/projects/pgsql/cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Connection.java,v

retrieving revision 1.18
diff -c -r1.18 Connection.java
*** src/interfaces/jdbc/org/postgresql/Connection.java  2001/07/15 04:21:26     1.18
--- src/interfaces/jdbc/org/postgresql/Connection.java  2001/07/19 14:17:52
***************
*** 8,13 ****
--- 8,14 ----
  import org.postgresql.fastpath.*;
  import org.postgresql.largeobject.*;
  import org.postgresql.util.*;
+ import org.postgresql.core.Encoding;
  
  /**
   * $Id: Connection.java,v 1.18 2001/07/15 04:21:26 momjian Exp $
***************
*** 33,43 ****
  
    /**
     *  The encoding to use for this connection.
-    *  If <b>null</b>, the encoding has not been specified by the
-    *  user, and the default encoding for the platform should be
-    *  used.
     */
!   private String encoding;
  
    public boolean CONNECTION_OK = true;
    public boolean CONNECTION_BAD = false;
--- 34,41 ----
  
    /**
     *  The encoding to use for this connection.
     */
!   private Encoding encoding = Encoding.defaultEncoding();
  
    public boolean CONNECTION_OK = true;
    public boolean CONNECTION_BAD = false;
***************
*** 162,168 ****
                // The most common one to be thrown here is:
                // "User authentication failed"
                //
!                 throw new SQLException(pg_stream.ReceiveString(getEncoding()));
  
              case 'R':
                // Get the type of request
--- 160,166 ----
                // The most common one to be thrown here is:
                // "User authentication failed"
                //
!                 throw new SQLException(pg_stream.ReceiveString(encoding));
  
              case 'R':
                // Get the type of request
***************
*** 232,238 ****
            break;
        case 'E':
        case 'N':
!            throw new SQLException(pg_stream.ReceiveString(getEncoding()));
          default:
            throw new PSQLException("postgresql.con.setup");
        }
--- 230,236 ----
            break;
        case 'E':
        case 'N':
!            throw new SQLException(pg_stream.ReceiveString(encoding));
          default:
            throw new PSQLException("postgresql.con.setup");
        }
***************
*** 244,354 ****
           break;
        case 'E':
        case 'N':
!            throw new SQLException(pg_stream.ReceiveString(getEncoding()));
          default:
            throw new PSQLException("postgresql.con.setup");
        }
  
-       // Originally we issued a SHOW DATESTYLE statement to find the databases 
default
-       // datestyle. However, this caused some problems with timestamps, so in 6.5, 
we
-       // went the way of ODBC, and set the connection to ISO.
-       //
-       // This may cause some clients to break when they assume anything other than 
ISO,
-       // but then - they should be using the proper methods ;-)
-       //
-       // We also ask the DB for certain properties (i.e. DatabaseEncoding at this 
time)
-       //
        firstWarning = null;
  
!       java.sql.ResultSet initrset = ExecSQL("set datestyle to 'ISO'; " +
!         "select case when pg_encoding_to_char(1) = 'SQL_ASCII' then 'UNKNOWN' else 
getdatabaseencoding() end");
  
!       String dbEncoding = null;
!       //retrieve DB properties
!       if(initrset.next()) {
! 
!         //handle DatabaseEncoding
!         dbEncoding = initrset.getString(1);
!         //convert from the PostgreSQL name to the Java name
!         if (dbEncoding.equals("SQL_ASCII")) {
!           dbEncoding = "ASCII";
!         } else if (dbEncoding.equals("UNICODE")) {
!           dbEncoding = "UTF8";
!         } else if (dbEncoding.equals("LATIN1")) {
!           dbEncoding = "ISO8859_1";
!         } else if (dbEncoding.equals("LATIN2")) {
!           dbEncoding = "ISO8859_2";
!         } else if (dbEncoding.equals("LATIN3")) {
!           dbEncoding = "ISO8859_3";
!         } else if (dbEncoding.equals("LATIN4")) {
!           dbEncoding = "ISO8859_4";
!         } else if (dbEncoding.equals("LATIN5")) {
!           dbEncoding = "ISO8859_5";
!         } else if (dbEncoding.equals("LATIN6")) {
!           dbEncoding = "ISO8859_6";
!         } else if (dbEncoding.equals("LATIN7")) {
!           dbEncoding = "ISO8859_7";
!         } else if (dbEncoding.equals("LATIN8")) {
!           dbEncoding = "ISO8859_8";
!         } else if (dbEncoding.equals("LATIN9")) {
!           dbEncoding = "ISO8859_9";
!         } else if (dbEncoding.equals("EUC_JP")) {
!           dbEncoding = "EUC_JP";
!         } else if (dbEncoding.equals("EUC_CN")) {
!           dbEncoding = "EUC_CN";
!         } else if (dbEncoding.equals("EUC_KR")) {
!           dbEncoding = "EUC_KR";
!         } else if (dbEncoding.equals("EUC_TW")) {
!           dbEncoding = "EUC_TW";
!         } else if (dbEncoding.equals("KOI8")) {
!         // try first if KOI8_U is present, it's a superset of KOI8_R
!           try {
!               dbEncoding = "KOI8_U";
!               "test".getBytes(dbEncoding);
!           }
!           catch(UnsupportedEncodingException uee) {
!           // well, KOI8_U is still not in standard JDK, falling back to KOI8_R :(
!               dbEncoding = "KOI8_R";
!           }
  
!         } else if (dbEncoding.equals("WIN")) {
!           dbEncoding = "Cp1252";
!         } else if (dbEncoding.equals("UNKNOWN")) {
!           //This isn't a multibyte database so we don't have an encoding to use
!           //We leave dbEncoding null which will cause the default encoding for the
!           //JVM to be used
!           dbEncoding = null;
!         } else {
!           dbEncoding = null;
!         }
!       }
  
  
!       //Set the encoding for this connection
!       //Since the encoding could be specified or obtained from the DB we use the
!       //following order:
!       //  1.  passed as a property
!       //  2.  value from DB if supported by current JVM
!       //  3.  default for JVM (leave encoding null)
!       String passedEncoding = info.getProperty("charSet");  // could be null
! 
!       if (passedEncoding != null) {
!         encoding = passedEncoding;
!       } else {
!         if (dbEncoding != null) {
!           //test DB encoding
!           try {
!             "TEST".getBytes(dbEncoding);
!             //no error the encoding is supported by the current JVM
!             encoding = dbEncoding;
!           } catch (UnsupportedEncodingException uee) {
!             //dbEncoding is not supported by the current JVM
!             encoding = null;
!           }
!         } else {
!           encoding = null;
!         }
        }
  
        // Initialise object handling
        initObjectTypes();
--- 242,275 ----
           break;
        case 'E':
        case 'N':
!            throw new SQLException(pg_stream.ReceiveString(encoding));
          default:
            throw new PSQLException("postgresql.con.setup");
        }
  
        firstWarning = null;
  
!       String dbEncoding;
  
!       // "pg_encoding_to_char(1)" will return 'EUC_JP' for a backend compiled with 
multibyte,
!       // otherwise it's hardcoded to 'SQL_ASCII'.
!       // If the backend doesn't know about multibyte we can't assume anything about 
the encoding
!       // used, so we denote this with 'UNKNOWN'.
  
!       final String encodingQuery =
!         "select case when pg_encoding_to_char(1) = 'SQL_ASCII' then 'UNKNOWN' else 
getdatabaseencoding() end";
  
+       // Set datestyle and fetch db encoding in a single call, to avoid making
+       // more than one round trip to the backend during connection startup.
  
!       java.sql.ResultSet resultSet =
!         ExecSQL("set datestyle to 'ISO'; " + encodingQuery);
! 
!       if (! resultSet.next()) {
!         throw new PSQLException("postgresql.con.failed", "failed getting backend 
encoding");
        }
+       dbEncoding = resultSet.getString(1);
+       encoding = Encoding.getEncoding(dbEncoding, info.getProperty("charSet"));
  
        // Initialise object handling
        initObjectTypes();
***************
*** 447,469 ****
            int update_count = 1;
            int insert_oid = 0;
            SQLException final_error = null;
- 
-           // Commented out as the backend can now handle queries
-           // larger than 8K. Peter June 6 2000
-           //if (sql.length() > 8192)
-           //throw new PSQLException("postgresql.con.toolong",sql);
- 
-         if (getEncoding() == null)
-             buf = sql.getBytes();
-         else {
-             try {
-                 buf = sql.getBytes(getEncoding());
-             } catch (UnsupportedEncodingException unse) {
-                  throw new PSQLException("postgresql.con.encoding",
-                                         unse);
-             }
-         }
  
            try
                {
                    pg_stream.SendChar('Q');
--- 368,375 ----
            int update_count = 1;
            int insert_oid = 0;
            SQLException final_error = null;
  
+           buf = encoding.encode(sql);
            try
                {
                    pg_stream.SendChar('Q');
***************
*** 484,490 ****
                        {
                        case 'A':       // Asynchronous Notify
                            pid = pg_stream.ReceiveInteger(4);
!                             msg = pg_stream.ReceiveString(getEncoding());
                            break;
                        case 'B':       // Binary Data Transfer
                            if (fields == null)
--- 390,396 ----
                        {
                        case 'A':       // Asynchronous Notify
                            pid = pg_stream.ReceiveInteger(4);
!                             msg = pg_stream.ReceiveString(encoding);
                            break;
                        case 'B':       // Binary Data Transfer
                            if (fields == null)
***************
*** 495,501 ****
                                tuples.addElement(tup);
                            break;
                        case 'C':       // Command Status
!                             recv_status = pg_stream.ReceiveString(getEncoding());
  
                                // Now handle the update count correctly.
                                if(recv_status.startsWith("INSERT") || 
recv_status.startsWith("UPDATE") || recv_status.startsWith("DELETE") || 
recv_status.startsWith("MOVE")) {
--- 401,407 ----
                                tuples.addElement(tup);
                            break;
                        case 'C':       // Command Status
!                             recv_status = pg_stream.ReceiveString(encoding);
  
                                // Now handle the update count correctly.
                                if(recv_status.startsWith("INSERT") || 
recv_status.startsWith("UPDATE") || recv_status.startsWith("DELETE") || 
recv_status.startsWith("MOVE")) {
***************
*** 537,543 ****
                                tuples.addElement(tup);
                            break;
                        case 'E':       // Error Message
!                             msg = pg_stream.ReceiveString(getEncoding());
                            final_error = new SQLException(msg);
                            hfr = true;
                            break;
--- 443,449 ----
                                tuples.addElement(tup);
                            break;
                        case 'E':       // Error Message
!                             msg = pg_stream.ReceiveString(encoding);
                            final_error = new SQLException(msg);
                            hfr = true;
                            break;
***************
*** 552,561 ****
                                hfr = true;
                            break;
                        case 'N':       // Error Notification
!                             addWarning(pg_stream.ReceiveString(getEncoding()));
                            break;
                        case 'P':       // Portal Name
!                             String pname = pg_stream.ReceiveString(getEncoding());
                            break;
                        case 'T':       // MetaData Field Description
                            if (fields != null)
--- 458,467 ----
                                hfr = true;
                            break;
                        case 'N':       // Error Notification
!                             addWarning(pg_stream.ReceiveString(encoding));
                            break;
                        case 'P':       // Portal Name
!                             String pname = pg_stream.ReceiveString(encoding);
                            break;
                        case 'T':       // MetaData Field Description
                            if (fields != null)
***************
*** 588,594 ****
  
        for (i = 0 ; i < nf ; ++i)
            {
!                 String typname = pg_stream.ReceiveString(getEncoding());
                int typid = pg_stream.ReceiveIntegerR(4);
                int typlen = pg_stream.ReceiveIntegerR(2);
                int typmod = pg_stream.ReceiveIntegerR(4);
--- 494,500 ----
  
        for (i = 0 ; i < nf ; ++i)
            {
!                 String typname = pg_stream.ReceiveString(encoding);
                int typid = pg_stream.ReceiveIntegerR(4);
                int typlen = pg_stream.ReceiveIntegerR(2);
                int typmod = pg_stream.ReceiveIntegerR(4);
***************
*** 653,663 ****
      }
  
      /**
!      *  Get the character encoding to use for this connection.
!      *  @return the encoding to use, or <b>null</b> for the
!      *  default encoding.
       */
!     public String getEncoding() throws SQLException {
          return encoding;
      }
  
--- 559,567 ----
      }
  
      /**
!      * Get the character encoding to use for this connection.
       */
!     public Encoding getEncoding() throws SQLException {
          return encoding;
      }
  
Index: src/interfaces/jdbc/org/postgresql/PG_Stream.java
===================================================================
RCS file: 
/home/projects/pgsql/cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/PG_Stream.java,v
retrieving revision 1.9
diff -c -r1.9 PG_Stream.java
*** src/interfaces/jdbc/org/postgresql/PG_Stream.java   2001/07/15 04:21:26     1.9
--- src/interfaces/jdbc/org/postgresql/PG_Stream.java   2001/07/19 14:17:52
***************
*** 10,16 ****
  import org.postgresql.util.*;
  
  /**
!  * @version 1.0 15-APR-1997
   *
   * This class is used by Connection & PGlobj for communicating with the
   * backend.
--- 10,16 ----
  import org.postgresql.util.*;
  
  /**
!  * $Id$
   *
   * This class is used by Connection & PGlobj for communicating with the
   * backend.
***************
*** 208,214 ****
     * @return string from back end
     * @exception SQLException if an I/O error occurs, or end of file
     */
!   public String ReceiveString(String encoding)
        throws SQLException
    {
      int s = 0;
--- 208,214 ----
     * @return string from back end
     * @exception SQLException if an I/O error occurs, or end of file
     */
!   public String ReceiveString(Encoding encoding)
        throws SQLException
    {
      int s = 0;
***************
*** 239,256 ****
        } 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;
    }
  
    /**
--- 239,245 ----
        } catch (IOException e) {
        throw new PSQLException("postgresql.stream.ioerror",e);
        }
!       return encoding.decode(rst, 0, s);
    }
  
    /**
Index: src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java
===================================================================
RCS file: 
/home/projects/pgsql/cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java,v

retrieving revision 1.16
diff -c -r1.16 ResultSet.java
*** src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java     2001/07/09 16:59:50    
 1.16
--- src/interfaces/jdbc/org/postgresql/jdbc1/ResultSet.java     2001/07/19 14:17:54
***************
*** 14,19 ****
--- 14,20 ----
  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,179 ****
     */
    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);
!         }
!     }
    }
    
    /**
--- 155,169 ----
     */
    public String getString(int columnIndex) throws SQLException
    {
      if (columnIndex < 1 || columnIndex > fields.length)
        throw new PSQLException("postgresql.res.colrange");
+ 
      wasNullFlag = (this_row[columnIndex - 1] == null);
      if(wasNullFlag)
        return null;
! 
!     Encoding encoding = connection.getEncoding();
!     return encoding.decode(this_row[columnIndex - 1]);
    }
    
    /**
Index: src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
===================================================================
RCS file: 
/home/projects/pgsql/cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java,v

retrieving revision 1.27
diff -c -r1.27 ResultSet.java
*** src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java     2001/06/11 22:12:00    
 1.27
--- src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java     2001/07/19 14:17:57
***************
*** 5,11 ****
  // 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.*;
--- 5,10 ----
***************
*** 15,20 ****
--- 14,20 ----
  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,187 ****
      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);
!         }
!     }
    }
  
    /**
--- 172,179 ----
      if(wasNullFlag)
        return null;
  
!     Encoding encoding = connection.getEncoding();
!     return encoding.decode(this_row[columnIndex - 1]);
    }
  
    /**
***************
*** 1006,1020 ****
  
      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);
!       }
      }
  
      /**
--- 998,1006 ----
  
      public java.io.Reader getCharacterStream(int i) throws SQLException
      {
!       Encoding encoding = connection.getEncoding();
!       InputStream input = getBinaryStream(i);
!       return encoding.getDecodingReader(input);
      }
  
      /**
Index: src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java
===================================================================
RCS file: 
/home/projects/pgsql/cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java,v

retrieving revision 1.3
diff -c -r1.3 JDBC2Tests.java
*** src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java     2001/02/14 17:45:17    
 1.3
--- src/interfaces/jdbc/org/postgresql/test/JDBC2Tests.java     2001/07/19 14:17:58
***************
*** 195,200 ****
--- 195,201 ----
      suite.addTestSuite(DriverTest.class);
      suite.addTestSuite(ConnectionTest.class);
      suite.addTestSuite(DatabaseMetaDataTest.class);
+     suite.addTestSuite(EncodingTest.class);
  
      // Connectivity/Protocols
  
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$
 */

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;
        }
    }
}

package org.postgresql.test.jdbc2;

import junit.framework.*;
import org.postgresql.core.Encoding;
import java.io.*;

/**
 * Tests for the Encoding class.
 *
 * $Id$
 */


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());
    }
}

---------------------------(end of broadcast)---------------------------
TIP 1: subscribe and unsubscribe commands go to [EMAIL PROTECTED]

Reply via email to