リレーショナルデータベースでinsertのトランザクションを実装

データベースの勉強に、ごつかわいいデータベースを実装しています。
http://d.hatena.ne.jp/nowokay/20120817#1345197962


リレーショナルデータベースとしての、演算的な機能は実装できてきたので、トランザクションに手をつけようかと思います。

Contextの導入

ということで、まずは実行管理をするためのContextを導入します。
いままでQueryクラスだったものをContextにして、fromメソッドをstaticメソッドからインスタンスメソッドに変更しています。
insertの起点になるintoメソッドも追加しました。


それから、単に補完が便利になるという理由で作ってたQueryObjインタフェースをクラスにして、Relationからはずしました。
Relationの各メソッドはTransactionを指定するようにしています。


ということで、呼び出し方がちょっとだけ変わって、次のようになりました。

Context ctx = new Context();
ctx.into(shohin).insert(1, "りんご", 1, 300);
System.out.println(ctx.from("shohin"));
System.out.println(ctx.from("shohin").lessThan("price", 250));

トランザクションの実装

とりあえず、insertにだけトランザクションを実装しました。
といっても、あまり複雑なことをしていなくて、タプルにトランザクションIDを指定するようにして、

public static class TableTaple extends Taple{
    Table parent;
    long oid;
    long createTx;
    long commitTx;

抽出時に未コミットのトランザクションを排除するようにしただけです。

public boolean isAvailableTaple(TableTaple taple){
    if(taple.isCommited()){
        return taple.commitTx < txid;
    }else{
        return taple.createTx == txid;
    }
}

つまり、トランザクションIDをバージョンとした、MVCC(マルチバージョン同時実行制御)です。

実行

コンテキストをもうひとつ用意しておきます。

Context ctx2 = new Context();


ctxコンテキストでトランザクションを開始して、商品を追加します。

ctx.begin();
ctx.into("shohin").insert(8, "レタス", 2, 250);


この時点では、未コミットなのでctx2からは見えません。

System.out.println("no commit from ctx2\n" + ctx2.from("shohin").equalsTo("shohin_id", 8));
no commit from ctx2
 |shohin.shohin_id|shohin.shohin_name|shohin.kubun_id|shohin.price|


ただし、同一トランザクションであるctxからは見えます。

System.out.println("no commit from ctx\n" + ctx.from("shohin").equalsTo("shohin_id", 8));
no commit from ctx
 |shohin.shohin_id|shohin.shohin_name|shohin.kubun_id|shohin.price|
 |8|レタス|2|250|


ctx2コンテキストで新しいトランザクションを開始して、ctxコンテキストでコミットしてみます。

ctx2.begin();
ctx.commit();


そうすると、コミット前にトランザクションを開始したのでctx2からは見えません。

System.out.println("commit from ctx2\n" + ctx2.from("shohin").equalsTo("shohin_id", 8));
ctx2.commit();
commit from ctx2
 |shohin.shohin_id|shohin.shohin_name|shohin.kubun_id|shohin.price|


もちろん、その後のトランザクションからは見えます。

System.out.println("commit from other ctx2\n" + ctx2.from("shohin").equalsTo("shohin_id", 8));
commit from other ctx2
 |shohin.shohin_id|shohin.shohin_name|shohin.kubun_id|shohin.price|
 |8|レタス|2|250|


なんだか、分離された感じになってますね。トランザクションっぽい。

ソース

ソースはこれ。
だいぶゴツくなってきました。
https://gist.github.com/3380142/432529263a5452b4336fdeec28957cf27dcfe5ec