世界線航跡蔵

Mad web programmerのYuguiが技術ネタや日々のあれこれをお送りします。

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はどうなってたろ。久しぶりに覗いてみよう。なんかお手伝いできそうなことがあれば...

トラックバック

http://yugui.jp/articles/572/ping
ruby|perl - 文字コードのちょっと高度な判定 (404 Blog Not Found)
これははっきり言って悩ましい。ですが、判定が曖昧な場合はその旨をきちんと通知するのがBetter Practiceではないかと思います。 Matzにっき(2007-01-03)手元のcalkiがUTF-8の「》」相当の文字(U+8BB)を含むエントリが文字化けするので、 nkf-utf8のソースを見...

コメント

arton (2006年12月27日 00時12分50秒)
<p> あー、確かにWin32OLE一族(ASR含む)は、Rubyの文字列とBSTRの相互変換についてはシステムのデフォルトロケールに従って$KCODEは無視してますね(ASRにいたっては勝手に$KCODE=&#39;s&#39;を設定してしまうし)。<br />その動作が問題になるとは思ってなかったけど今となってはちょっとまずかったみたいですね(ruby-listで提案すると助田さんが何か考えてくれるかも。おそらく互換性問題は起きないはずなので)</p>
arton (2006年12月30日 22時05分28秒)
<p>上でああいうコメント書いたけど、既にWin32OLEは対応済みでした。<br />$KCODE = &#39;u&#39; の場合には、Win32OLEの利用前に<br />WIN32OLE.codepage = WIN32OLE::CP_UTF8<br />を実行すると、BSTR変換時に、RubyのStringをUTF-8として扱います。<br /></p>
Yugui (2006年12月30日 23時05分51秒)
<p>artonさん、ありがとうございます。</p> <p>会社に行かないとSQL Server環境がないのですが、年明けに試してみます。</p>
Yugui (2007年01月09日 15時59分59秒)
<p>WIN32OLE.codepage = WIN32OLE::CP_UTF8でうまくいきました。artonさんありがとうございます。</p> <p>require &#39;dbi&#39;<br />require &#39;iconv&#39;</p> <p>$KCODE = &#39;s&#39;<br />value = &#39;てすと&#39;<br />usql = &quot;INSERT INTO hoge(val) VALUES(&#39;#{Iconv.conv(&#39;UTF-8&#39;, &#39;CP932&#39;, value)}&#39;)&quot;</p> <p>$KCODE = &#39;u&#39;<br />WIN32OLE.codepage = WIN32OLE::CP_UTF8<br />DBI.connect(connect_string).execute(usql) # ok</p>
blog comments powered by Disqus

ご案内

前の記事
次の記事

タグ一覧

過去ログ

  1. 2016年07月
  2. 2016年01月
  3. 2015年09月
  4. 2015年08月
  5. 過去ログ一覧

フィード

フィードとは

その他

Powered by "rhianolethe" the blog system