RubyでBerkeley DB(3)
前回,RubyのBerkeley DBのAPIで,任意の型を強制的に変換して使う方法を書いたのですが,
RubyでのBerkeley DBの型 - なぜか数学者にはワイン好きが多い
これ,デフォルトではdbmやgdbmライブラリと同じく数値も(他のオブジェクトも全て)string型に変換されてしまうために,「1」という整数を文字列の「"123"」(=a["aaa"]の結果,返ってくる値)に足そうとして失敗しているからです.
なんのことはない,バークレーDBのAPIライブラリのサンプルプログラムに,もっともっと簡単な方法が使われていました.
まず,以前にも記述したように,BDBに文字列として格納されてしまうために数値データの扱いに失敗する例です.
- write.rb
#!/usr/bin/ruby require 'bdb'; a = BDB::Btree::open("./testdb","table1","w",0777); a["aaa"] = 123; a.close;
- read.rb
#!/usr/bin/ruby require 'bdb'; a = BDB::Btree::open("./testdb","table1","r",0777); p a["aaa"]+1; a.close;
- 連続実行結果
$ ./write.rb; ./read.rb read.rb:4:in `+': can't convert Fixnum into String (TypeError)
これは,こう書くべきだそうです.
- write.rb
#!/usr/bin/ruby require 'bdb'; a = BDB::Btree::open("./testdb","table1","w","marshal"=>true); a["aaa"] = 123; p a["aaa"]; a.close;
- read.rb
#!/usr/bin/ruby require 'bdb'; a = BDB::Btree::open("./stestdb","table1","r","marshal"=>true); p a["aaa"]+1; a.close;
- 連続実行結果
$ ./write.rb; ./read.rb 123 124
RubyにデフォルトでくっついてくるMarshalのmix-inを使えば,自分で書いた
一応,それらしく動いているようです.
が...これじゃ,string型しか扱えないdbmを使っているのと大差無い気もしますね...
Bekeley DBのC++用のAPIだと,型がstring型と違っても,強引にストアしたいオブジェクトのサイズを取得してBerkeley DB内に容量を確保し,バイト単位でコピーするというサンプルを良く見かけます.Rubyでもそうやれば良いのでしょうかねぇ...なんかオブジェクト指向っぽくない...スマートにオブジェクトそのものをDBに出し入れする方法は...
ということが,解決できるようです.