Ruby1.8+DBI::SQLite その2

このまえの続き


結局、SQLite.cをのぞいてみたら、どこにも last_insert_rowid()らしきものはなし。ということで、どうあがいても使えないという結論になりました。


しゃーないので、自力でセコセコつくることに。といっても前後を眺めて、見よう見まねです。で、気がついたら、Rubyプログラムを始めたのに、Cプログラムばっかり眺めている自分がいました。(笑)


個人的にワタシは最終的なアプリを作ることに快感を感じるほうなんで、この手の言語とかモジュールの開発はしないに越したことはないと思うほうなんですが、こういう現状じゃ、しゃーないですね。


とりあえず、パッチもできたので、そのまま作者に報告。以外とこころよい返事が頂けたのが唯一の救いです。


パッチ

*** SQLite.c- Mon Jun 21 21:53:35 2004
--- SQLite.c Mon Jun 21 23:40:38 2004
***************
*** 317,322 ****
--- 317,334 ----
}

static VALUE
+ Database_last_insert_rowid(int argc, VALUE *argv, VALUE self)
+ {
+ int state;
+ struct sDatabase *db;
+
+ Data_Get_Struct(self, struct sDatabase, db);
+ state = sqlite_last_insert_rowid(db->conn);
+
+ return INT2FIX(state);
+ }
+
+ static VALUE
Database_do(int argc, VALUE *argv, VALUE self)
{
/* argv[0] = stmt
***************
*** 857,862 ****
--- 869,876 ----
rb_define_method(cDatabase, "[]", Database_aref, 1);
rb_define_method(cDatabase, "[]=", Database_aset, 2);
rb_define_method(cDatabase, "columns", Database_columns, 1);
+ rb_define_method(cDatabase, "__last_insert_rowid", Database_last_insert_rowid, -1);
+

rb_include_module(cDatabase, rb_eval_string("DBI::SQL::BasicBind"));

サンプル

#!/usr/local/bin/ruby

require 'dbi'
dbh = DBI.connect('DBI:SQLite:mydb')

begin
dbh.do('create table test (test_id integer not null primary key, test_num integer)')
rescue
end

(1..10).each{|i|
dbh.do("insert into test (test_num) VALUES(#{i})")
p dbh.func('last_insert_rowid', nil)
}

dbh.do('commit')
dbh.disconnect

追記

前回のBlogでAutoCommit => trueとするとロックされてブロックされると記述しましたが、実際は逆です。(単純なプログラムコードのケアレスミス)]

このあたりの仕組みもソースをざっと眺めたので、気が向いたら詳しく書こうと思います。