PostgreSQL 6.4 JDBC ドライバ MB サポートパッチ 1998 12/14 PostgreSQL 6.4 の JDBC ドライバで、バックエンドの 文字エンコーディングを指定できるよう拡張するパッチです。 src/interfaces/jdbc/ の下で、 % patch -p1 < このファイル でパッチをあてて下さい。 使い方は、src/interfaces/jdbc/ の README.mb.eucjp か、 http://www.yo.rim.or.jp/~mochid/postgresql-jdbc/ を見て下さい。 private: mochid@yo.rim.or.jp 持田 修司 -- Do not crack your dream. Be MI by NetBSD -- diff -urN jdbc-6.4.ORIG/README.mb.eucjp jdbc-6.4-mb/README.mb.eucjp --- jdbc-6.4.ORIG/README.mb.eucjp Thu Jan 1 09:00:00 1970 +++ jdbc-6.4-mb/README.mb.eucjp Mon Dec 14 23:33:26 1998 @@ -0,0 +1,128 @@ + + $Id: README.mb.eucjp,v 1.2 1998/12/14 14:33:11 mochid Exp mochid $ + +PostgreSQL JDBC ドライバ マルチバイト パッチ + + PostgreSQL 6.4 の JDBC ドライバで、バックエンドとの + 文字エンコーディングを指定できるよう拡張するパッチです。 + +1. 使用できるエンコーディング名 + + エンコーディングは、Java のエンコーディング名で指定します。Java で + 有効なエンコーディング名は、下記が参考になります。 + + http://java.sun.com:80/products/jdk/1.1/intl/html/intlspec.doc7.html#20888 + Java Supported Encodings (1.1.5 以前) + + http://www.javasoft.com:80/products/jdk/1.1/docs/guide/intl/encoding.doc.html" + Java Supported Encodings (1.1.6 以降) + + ただし、"EUC_JP" と "UNICODE" は、それぞれ "EUCJIS"、"UTF8" として + 解釈します。PostgreSQL 6.4 がサポートしているエンコーディングは、 + ソースコードの postgresql-v6.4/doc/README.mb.jp や、石井さんの + + http://www.sra.co.jp/people/t-ishii/postgres95/6.4/changes.html + PostgreSQL 6.3.2 から 6.4 への変更点 + + にあります。 + + MULE_INTERNAL は、使用できません。 + +2. 指定方法 + + このパッチのあたったドライバは、次の 3 通りの方法でエンコーディング名を + 取得します。 + + 1) 接続時にバックエンドから取得 + 2) URL から取得 + 3) Java のシステムプロパティから取得 + + あとのものほど優先順位が高いです。バックエンドからの取得は、SQL + + select databaseencoding() + + によって取得します。通常は、これだけで動作する(つまり、何も指定しなくて + よい)と思います。エンコーディングを明示的に指示したい場合のみ、 + URL やシステムプロパティに指定します。 + + URL は、 + + jdbc:postgresql[.<エンコーディング名>]://<ホスト名>[:<ポート番号>]/ + + で指定します。 + + 例) jdbc:postgresql.EUC_JP://bigsrv.my.domain/database1 + + Java のシステムプロパティは、 postgresql.databaseencoding に + 指定します。 + + -Dpostgresql.databaseencoding=EUC_JP + +3. オリジナルとの互換性 + + オリジナルの JDBC ドライバは、String <-> byte[] 変換時に、 + エンコーディング指定をしないメソッドを使っています。これと互換性を保つ + ために、ドライバ内で取得したエンコーディング名が "SQL_ASCII" だった + 場合には、エンコーディング指定をしないメソッドを使うようにしてあります。 + エンコーディング指定がない、ということは、ファイル入出力用の + エンコーディング情報(Java の file.encoding システムプロパティで参照可)を + 使った変換が行われるので、明示的に "ASCII" を指定した場合とは + 違う動作となります。 + +4. 履歴 + + ・ 1998 12/14 6.4 対応、URL 指定できるように変更 + ・ 1998 9/30 たかばとしはる さんが pgsql-jp メーリングリストで 6.3 用に + 「jdbc UTF8 patch」 + + http://www.sra.co.jp/people/t-ishii/postgres95/mhonarc/pgsql-jp/1998Mar/msg00185.html + [pgsql-jp 3617] + + として公開されたものを他のエンコーディングでも利用できるよう修正 + +5. このパッチの取り扱いについて + + このパッチは、無保証です。このパッチによってなんらかの損害が発生する + 可能性がありますので、自らの責任において使用して下さい。 + 再配布は自由に行ってもらって結構です。ただし、修正されたものを + 配布される場合は、その旨を明記して下さい。 + +6. その他 + + i) Java のファイル入出力エンコーディングについて: + + Java は、文字列を内部ではユニコードで扱いますが、ファイルや + Socket を読み書きする時には、そのシステムのデフォルトの + エンコーディングに変換を行います。通常は、OS の + ローケール機構等によってデフォルトのエンコーディングが + 自動的に決定されます(したがって意識しなくてよいです)が、 + file.encoding システムプロパティで取得したり設定できる + ようで、Java がちゃんとサポートしていない環境等では + 明示的に指定して使います。 + + PostgreSQL バックエンドが使うデータベースのエンコーディングは + PostgreSQL コンパイル時と DB 作成時に決定されますが、これと + ファイル入出力エンコーディングが同一の場合は、このパッチを + 当てなくてもマルチバイトを正常に扱えると思います。 + + ii) 確認したプラットホームについて: + + パッチの作成・動作確認は、 + + NetBSD 1.3.2/i386 + JDK 1.1.5 (http://www.quick.com.au/java/) + file.encoding プロパティ EUC_JP + バックエンド EUC_JP + + で行いました。 + + iii) 関連情報 + + このパッチ用のページ + http://www.yo.rim.or.jp/~mochid/postgresql-jdbc/ + PostgreSQL ML + http://www.sra.co.jp/people/t-ishii/postgres95/ML/info.html + + + 持田 修司 mochid@yo.rim.or.jp + +# End of file diff -urN jdbc-6.4.ORIG/postgresql/Connection.java jdbc-6.4-mb/postgresql/Connection.java --- jdbc-6.4.ORIG/postgresql/Connection.java Thu Oct 8 09:38:20 1998 +++ jdbc-6.4-mb/postgresql/Connection.java Thu Dec 10 23:46:33 1998 @@ -115,6 +115,40 @@ // Now handle notices as warnings, so things like "show" now work protected SQLWarning firstWarning = null; + // Encoding string PostgreSQL -> Java mapping + class EncodingTable extends Hashtable + { + final String[] encodingStrs = { + "EUC_JP", "EUCJIS", /* use EUCJIS for JDK 1.1.5 */ + "UNICODE", "UTF8" + /* "MULE_INTERNAL" is not supported */ + }; + + EncodingTable() + { + super(); + for (int i = 0, len = encodingStrs.length; i < len;) + this.put(encodingStrs[i++], encodingStrs[i++]); + } + + // convert encoding name to Java complient + private String mapString(String instr) + { + if (instr == null) + return null; + String ecMapped = (String)this.get(instr); + if (ecMapped != null) + return ecMapped; + else + return instr; + } + }; + + static String dbEncodingPropName = "postgresql.databaseencoding"; + + boolean needConvertEncodingFlag = false; // need encoding conversion + String databaseEncoding = null; // set default encoding + /** * Connect to a PostgreSQL database back end. * @@ -268,6 +302,49 @@ // Initialise object handling initObjectTypes(); + // Get Database encoding + // + EncodingTable ecTbl = new EncodingTable(); + databaseEncoding = ecTbl.mapString(databaseEncoding); + + // get from Java Property + String encoding = System.getProperty(dbEncodingPropName); + if(encoding == null) // get from URL + encoding = info.getProperty("Protocol.encoding"); + encoding = ecTbl.mapString(encoding); + + // get from database + String ecFromDb = null; + ResultSet r = null; + try{ + r = ExecSQL("select getdatabaseencoding()"); + } catch(SQLException e) { + // do nothing. + } + if (r != null) { + r.next(); + ecFromDb = r.getString(1); + ecFromDb = ecTbl.mapString(ecFromDb); + } + + if(encoding == null) + encoding = ecFromDb; + else { + if ((!ecFromDb.equals("SQL_ASCII")) && (!ecFromDb.equals(encoding))) + System.err.println("Encoding " + encoding + + " does not match with database's " + ecFromDb + "."); + } + + if (encoding != null) + databaseEncoding = encoding; + + if (databaseEncoding == null || databaseEncoding.equals("SQL_ASCII")) + needConvertEncodingFlag = false; + else + needConvertEncodingFlag = true; + + pg_stream.cacheEncoding(this); + // Mark the connection as ok, and cleanup clearWarnings(); PG_STATUS = CONNECTION_OK; @@ -653,7 +730,15 @@ try { pg_stream.SendChar('Q'); - buf = sql.getBytes(); + if (!needConvertEncodingFlag) + buf = sql.getBytes(); + else { + try { + buf = sql.getBytes(databaseEncoding); + } catch (UnsupportedEncodingException e) { + throw new SQLException("Encode Error: " + e.toString()); + } + } pg_stream.Send(buf); pg_stream.SendChar(0); pg_stream.flush(); @@ -1031,6 +1116,14 @@ { for(int i=0;i 0) { urlProps.put("Protocol",token); - found=true; + if (encoding != null) + urlProps.put("Protocol.encoding", encoding); } } } diff -urN jdbc-6.4.ORIG/postgresql/PG_Stream.java jdbc-6.4-mb/postgresql/PG_Stream.java --- jdbc-6.4.ORIG/postgresql/PG_Stream.java Thu Sep 3 11:31:34 1998 +++ jdbc-6.4-mb/postgresql/PG_Stream.java Fri Dec 11 00:05:40 1998 @@ -31,6 +31,10 @@ // This is the error message returned when flushing the stream. private static final String FLUSH_MSG = "Error flushing output: "; + // for charactor encoding conversion + boolean needConvertEncodingFlag = false; // need encoding conversion + String databaseEncoding = null; + /** * Constructor: Connect to the PostgreSQL back end and return * a stream connection. @@ -270,7 +274,19 @@ } catch (IOException e) { throw new SQLException(IOE_MSG + e.toString()); } - String v = new String(rst, 0, s); + + String v = null; + if(!needConvertEncodingFlag) + v = new String(rst, 0, s); + else { + try + { + v = new String(rst, 0, s, databaseEncoding); + } catch (UnsupportedEncodingException e) { + throw new SQLException("Encode Error: " + e.toString()); + } + } + return v; } @@ -381,5 +397,11 @@ pg_output.close(); pg_input.close(); connection.close(); + } + + public void cacheEncoding(Connection jdbcConn) + { + needConvertEncodingFlag = jdbcConn.needConvertEncoding(); + databaseEncoding = jdbcConn.getDatabaseEncoding(); } } diff -urN jdbc-6.4.ORIG/postgresql/ResultSet.java jdbc-6.4-mb/postgresql/ResultSet.java --- jdbc-6.4.ORIG/postgresql/ResultSet.java Thu Sep 3 11:31:37 1998 +++ jdbc-6.4-mb/postgresql/ResultSet.java Fri Dec 11 00:22:19 1998 @@ -61,6 +61,8 @@ Connection connection; // the connection which we returned from SQLWarning warnings = null; // The warning chain boolean wasNullFlag = false; // the flag for wasNull() + boolean needConvertEncodingFlag = false; // need encoding conversion + String databaseEncoding = null; // database encoding // We can chain multiple resultSets together - this points to // next resultSet in the chain. @@ -86,6 +88,8 @@ this.updateCount = updateCount; this.this_row = null; this.current_row = -1; + this.needConvertEncodingFlag = this.connection.needConvertEncoding(); + this.databaseEncoding = this.connection.getDatabaseEncoding(); } /** @@ -161,7 +165,17 @@ wasNullFlag = (this_row[columnIndex - 1] == null); if(wasNullFlag) return null; - return new String(this_row[columnIndex - 1]); + if(!needConvertEncodingFlag) + return new String(this_row[columnIndex - 1]); + else { + String v = null; + try { + v = new String(this_row[columnIndex - 1], databaseEncoding); + } catch(UnsupportedEncodingException e) { + throw new SQLException("Encode Error: " + e.toString()); + } + return v; + } } /**