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に出し入れする方法は...

ということが,解決できるようです.