ratio - rational - irrational

« 不快に基づく排除 | Main | 途中でコミットできるトランザクション »

2006年12月26日

Rails + SQLServerでクエリがシンタックスエラーな件

$KCODE = 'u'でrailsを動かすとSQLServerへのクエリがエラーを起こすんだが。 前にメーリングリストでも見かけたことがあったような。で、$KCODE = 's'で我慢しるってことだったような。

ちょっと試してみた。

どうも、ADODBをラップしてるWin32OLEのRuby StringとBSTRの変換が問題なような感触。

require 'dbi'
require 'iconv'

$KCODE = 's'
value = 'てすと'
sql = "INSERT INTO hoge(val) VALUES('#{value}')"
usql = "INSERT INTO hoge(val) VALUES('#{Iconv.conv('UTF-8', 'CP932', value)}')"
DBI.connect(connect_string).execute(sql) # => ok
DBI.connect(connect_string).execute(usql) # => データが化ける

$KCODE = 'u'
DBI.connect(connect_string).execute(sql)
 # =>
   DBI::DatabaseError: Execute
   OLE error code:80040E14 in Microsoft OLE DB Provider for SQL Server
     文字列 ')' の前で引用符が閉じていません。
   HRESULT error code:0x80020009
     例外が発生しました。
       from /usr/lib/ruby/1.8/DBD/ADO/ADO.rb:135:in `execute'
       from /usr/lib/ruby/site_ruby/1.8/dbi.rb:888:in `execute'
       from /usr/lib/ruby/site_ruby/1.8/dbi.rb:480:in `execute'
       from (irb):66
       from :0

DBI.connect(connect_string).execute(usql) # => データが化ける

ということは、ADO.rbで使えるようなADODB.Connectionのラッパを拡張ライブラリで書いてやればいけるのか。 まぁ、そんなことしなくても、セッションに紐付いたコードページを変更してそれに合わせてサーバー側で変換させられれば良いんだけど。でも、その辺の設定がどうしてもわからない。"SET LANGUAGE = "は違うよな。

つーか、Rubyは文字列のエンコーディング周りは遅れてる。Stringが文字列といいつつ実際のところバイト列であるのが痛い。文字列オブジェクトを名乗るからには自分のエンコーディングは知っててほしいよね。エンコーディング情報が文字列オブジェクトじゃなくて$KCODEにあるせいで、エンコーディング混在が難しいわけだ。

Perl5はよーでけとるよなぁ。Encode.pmもあるし羨ましい。

Rubyも2.0ではその辺はなんとかなる予定らしいけれど、2.0リリースより先にm17nがマージされたりしないのかな。そういえばm17nはどうなってたろ。久しぶりに覗いてみよう。なんかお手伝いできそうなことがあれば...



トラックバック

この記事のトラックバックpingのURL:
http://idm.s9.xrea.com/blog/mt-tb.cgi/570

Ping元:ruby|perl - 文字コードのちょっと高度な判定

概要:
これははっきり言って悩ましい。ですが、判定が曖昧な場合はその旨をきちんと通知するのがBetter Practiceではないかと思います。 Matzにっき(2007-01-03)手元のcalkiがUTF-8の「》」相当の文字(U+8BB)を含むエントリが文字化けするので、 nkf-utf8のソースを見...
Weblog:
404 Blog Not Found
日時:
2007年01月11日 21:25

コメント

 あー、確かにWin32OLE一族(ASR含む)は、Rubyの文字列とBSTRの相互変換についてはシステムのデフォルトロケールに従って$KCODEは無視してますね(ASRにいたっては勝手に$KCODE='s'を設定してしまうし)。
その動作が問題になるとは思ってなかったけど今となってはちょっとまずかったみたいですね(ruby-listで提案すると助田さんが何か考えてくれるかも。おそらく互換性問題は起きないはずなので)

  • Posted by: arton at 2006年12月27日 00:12

上でああいうコメント書いたけど、既にWin32OLEは対応済みでした。
$KCODE = 'u' の場合には、Win32OLEの利用前に
WIN32OLE.codepage = WIN32OLE::CP_UTF8
を実行すると、BSTR変換時に、RubyのStringをUTF-8として扱います。

  • Posted by: arton at 2006年12月30日 22:05

artonさん、ありがとうございます。

会社に行かないとSQL Server環境がないのですが、年明けに試してみます。

  • Posted by: Yugui at 2006年12月30日 23:05

WIN32OLE.codepage = WIN32OLE::CP_UTF8でうまくいきました。artonさんありがとうございます。

require 'dbi'
require 'iconv'

$KCODE = 's'
value = 'てすと'
usql = "INSERT INTO hoge(val) VALUES('#{Iconv.conv('UTF-8', 'CP932', value)}')"

$KCODE = 'u'
WIN32OLE.codepage = WIN32OLE::CP_UTF8
DBI.connect(connect_string).execute(usql) # ok

  • Posted by: Yugui at 2007年01月09日 15:59

新しくコメントをつける

よくわからない理由により、コメントが即座には反映されないかもしれませんか゛、ボタンを押して元の画面に戻ってきたならたぶん正しく送信されています。




blog操作

検索


カテゴリー

このブログについて

あわせて読みたい

follow yugui at http://twitter.com
© 2006 Yugui

Powered by Movable Type 3.2-ja-2