スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

rubyのpgで配列型の扱いについて

rubyのPostgreSQLドライバーのpgでの配列の扱いについて調べてみました。
まずざくっと実装。

#coding:utf-8
require 'pg'
conn = nil
begin
conn = PGconn.connect("localhost",5432,"","","test","user","password")
conn.exec("BEGIN")
conn.exec("insert into t_test(aaa) values ($1)", [["a","b","c"]])
res = conn.exec("select * from t_test")
res.each do |it|
p it
end
conn.exec("delete from t_test")
conn.exec("COMMIT")
rescue Exception => e
p e
conn.exec("ROLLBACK") if conn
end

動かしてみると、こんなエラーが出ました。

#<PG::Error: ERROR: missing dimension value

rubyの配列渡すだけじゃだめみたいです。
ということで、配列のリテラル表現でわたしてみました。

conn.exec("insert into t_test(aaa) values ($1)", ["{a,b,c}"])

実行結果は以下の通り。

{"aaa"=>"{a,b,c}"}

一応やりとりできました。
でも、これちょっと使いにくいです。
そこで、rubyの配列を受け取ってinsertできる文字列に変換するgenerateと
selectの結果の文字列からrubyの配列に変換するparseをつくりました。
#coding:utf-8
require 'pg'

def parse(src)
return nil if !src
return [] if src.empty? || "{}" == src
res = []
count = src.size - 2
item = ''
quote = false
bs = false
for i in 1..count
if "\\" == src[i]
if bs
item += "\\"
bs = false
else
bs = true
end
elsif ',' == src[i]
if quote
item += ','
else
res << item
item = ''
end
elsif '"' == src[i]
if bs
item += '"'
elsif quote
quote = false
else
quote = true
end
else
if bs
item += "\\"
end
item += src[i]
end
if "\\" != src[i]
bs = false
end
end
if '' != item
res << item
end
res
end

def generate(src)
return '{}' if src.length == 0
res = '{'
src.each do |it|
res += '"' + it.gsub(/\\/, "\\\\\\\\").gsub(/"/, "\\\"") + '"'
res += ','
end
res[0, res.length-1] + '}'
end

conn = nil
begin
conn = PGconn.connect("localhost",5432,"","","test","user","password")
conn.exec("BEGIN")
val = ["a,b", "b{", "c\"b", "d\\e", "f\ng"]
conn.exec("insert into t_test(aaa) values ($1)", [generate(val)])
res = conn.exec("select * from t_test")
res.each do |it|
p val
p parse(it['aaa'])
end
conn.exec("delete from t_test")
conn.exec("COMMIT")
rescue Exception => e
p e
conn.exec("ROLLBACK") if conn
end


動作結果は以下の通り。

["a,b", "b{", "c\"b", "d\\e", "f\ng"]
["a,b", "b{", "c\"b", "d\\e", "f\ng"]

いままで配列型を渡すときは、カンマ区切りの文字列にしてストアードプロシージャーで配列に戻していました。
これの最大の欠点は文字列の中にカンマが入れられないこと。
これがあればどんな文字列も扱えます。
スポンサーサイト

COMMENTS

COMMENT FORM

TRACKBACK


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。