[pgsql-jp: 36844] client encoding と PQexec

Jun Kuriyama kuriyama @ imgsrc.co.jp
2006年 3月 9日 (木) 10:26:23 JST


 はじめまして。

 従来 Shift_JIS な HTML を生成する Perl CGI で、EUC-JP な PostgreSQL
DB からデータを持ってくるのに、Jcode.pm などを使って値を明示的に変換す
る、ということをしていたのですが、ちょっと今回 client encoding を指定
する機能を使ってみようと思いました。

 そこで、以下のようなスクリプトを書いてみたのですが、サーバが
PostgreSQL 8.0.7 の環境では問題なく動作し、7.4.12 の環境では
"unterminated quoted string" といわれてしまう現象に遭遇してしまいまし
た。
 ざっと検索した所、DB が EUC-JP で client encoding が "SJIS" な状況、
というのは結構ある状況のようなので、何か私が根本的な所を見落としている
気がするのですが、何かヒントいただけますでしょうか?


----- test.pl (このファイル自体は EUC-JP)
#!/usr/bin/perl -w
#
# % createdb -O www -E EUC_JP test
#
# psql> create table test (value text);
#

use strict;
use DBI;
use Jcode;

$ENV{PGCLIENTENCODING} = "SJIS";
my $dbh = DBI->connect("dbi:Pg:dbname=test", "www", "", { AutoCommit => 0 })
  or die;

my $sth = $dbh->prepare("insert into test (value) values (?)")
  or die;
$sth->execute(Jcode->new("ヘソ", "euc")->sjis) or die;
$dbh->rollback;
-----


 ざっとこちらで追った所を書いておきます。

 "ソ" は Shift_JIS で 0x835c で、末尾に 0x5c ('\' 文字) が来ているの
が発生条件です。

 Perl の DBI (DBD::Pg) では、サーバ側が 8.x の時、もしくは 7.4.x で一
定の条件の時には libpq の PQexecPrepared() を使いますが、それ以外では
自前 (DBD::Pg 側) で quote などを行って、placeholder の部分にも値を納
めた状態のひとつの SQL 文にしてから PQexec() に渡します。
 PQexecPrepared() を使う場合は問題が無く、以下は 7.4.12 で PQexec() 
を使う時の話です。

 ここで、server encoding が EUC-JP で client encoding が SJIS の場合、
DBD::Pg の層では SJIS なので、SQL 文を組み立てる際に上記の statement
は

insert into test (value) values ('ヘソ\')

と quote された状態になり、これが PQexec() に渡ります。

 サーバ側では、それを Q (simple query) メッセージとして受け取り、
pq_getmsgstring() 内で SJIS --> EUC-JP の変換を行っているようです。す
ると、EUC-JP への変換後も

insert into test (value) values ('ヘソ\')

となってしまい、EUC-JP では 'ソ' は 0xa5bd なので、末尾の \ は単独で残
ることになり、

ERROR: unterminated quoted string at or near "'ヘソ\')" at character 34

となってしまいます。

 DBD::Pg が自前で quote している時点で負けな気がするのですが、古いサー
バにも対応できるように、ということでこういうコードになっているようです。

 client encoding が効いているときに、PQexec() が受け取るべき SQL が、
client encoding の状態で valid であるべきか、server encoding に変換し
た状態で valid であるべきか、を理解していないので、どのあたりが問題な
のかもよくわかっていませんが……。


# 今回使ったバージョン:
#   FreeBSD 5.4
#   PostgreSQL 7.4.12
#   Perl 5.8.8
#     DBI 1.50
#     DBD::Pg 1.43


-- 
Jun Kuriyama <kuriyama @ imgsrc.co.jp> // IMG SRC, Inc.



pgsql-jp メーリングリストの案内