Ruby Sequel Oracle Sequence Literal

INSERT文を実行する場合にOracleのSequenceを利用してプライマリキーを自動でインクリメントしていくようなパターンのときに、なぜかリテラルがうまいこと動かなかったのでメモ。

シーケンスを取得する際に、次の通りbindを使って文字列として設定してしまうと、バインド変数使用時の ORA-01722 エラーが発生します

DB[:items].insert(:a => 1, :b => "user_seq.nextval")
# INSERT INTO items (a, b) VALUES ("1", "user_seq.nextval")

また、Sequel::Dataset クラスにある literal を使っても、同様にORA-01722 エラーが発生します

DB[:items].insert(:a => 1, :b => DB[:items].literal('users_seq.nextval'))
# INSERT INTO items (a, b) VALUES ("1", '"user_seq"."nextval"')

そこで、リテラルには、シンボルを使ってデータ型で対応します
その際、シーケンス名と次の値を取得する nextval の間を __ (アンダースコアx2)で繋げます

DB[:items].insert(:a => 1, :b => :users_seq__nextval)
# INSERT INTO items (a, b) VALUES ("1", "user_seq"."nextval")

"user_seq"."nextval"のような形にすることで、Oracleが代入時に実行する暗黙変換がうまいこと比較されます。

http://www.st-hatena.com/users/sa/samril/user_p.gifガチで悩んだ