H2Databaseを追っかけていたりしたブログ

H2 database のリリースノートを読んだりとか。

H2でユーザ定義関数/ストアドプロシージャを試してみる2

ユーザー定義関数の返りをテーブル代わりに使ってみます。テーブル代わりに使う場合には、メソッドはResultSetを返すものである事が必要です。

それ以外、実装で特に難しいところはありませんが、ユーザ定義関数をテーブルとして扱うときには、少なくとも2回のメソッドの実行が発生する、ということに注意が必要です。具体的には、SQLをパースして、カラム情報を取得するとき、それと実施するときです。サンプルにもあるように、カラム情報を取得するときにはconn.getMetaData().getURL()で、返ってくる値が"jdbc:columnlist:connection"になるので、それを確認したら、とりあえずカラム情報だけ作成して、さっさとResultSetを返してしまいます。

package com.karatebancho;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.Timestamp;
import java.sql.Types;

import org.h2.tools.SimpleResultSet;

import twitter4j.Status;
import twitter4j.Twitter;
import twitter4j.TwitterFactory;

public class Timeline {
	public static ResultSet twitter(Connection conn) throws Exception{
	    SimpleResultSet rs = new SimpleResultSet();
	    rs.addColumn("tweet", Types.VARCHAR, 140, 0);
	    rs.addColumn("createdat", Types.TIMESTAMP, 10, 0);
	    String url = conn.getMetaData().getURL();
	    if (url.equals("jdbc:columnlist:connection")) {
	        return rs;
	    }

		Twitter twitter = new TwitterFactory().getInstance(System.getProperty("twitter.id"),System.getProperty("twitter.password"));
		for(Status status : twitter.getHomeTimeline()){
			rs.addRow(status.getText(), new Timestamp(status.getCreatedAt().getTime()));
		}
		
		return rs;
	}
}


クラスパスに入れて、H2を起動。

java -Dtwitter.id=ysobj -Dtwitter.password=xxxxxx -cp h2-1.2.132.jar:function.jar:twitter4j-core-2.1.1.jar org.h2.tools.Shell -url jdbc:h2:mem:

ユーザ定義関数を設定して、

sql> create alias timeline for "com.karatebancho.Timeline.twitter";
(Update count: 0, 48 ms)

実行!(fetch first ... はDB2での先頭N行を取得するときの記法)

sql> set MODE DB2;
(Update count: 0, 5 ms)
sql> select * from timeline() fetch first 1 rows only;
tweet          |createdat
H2でユーザ定義関数とか作って|2010-04-16 01:2
(data is partially truncated)
(1 row, 1884 ms)

さくっとできた。たったこれだけで、他のテーブルとjoinできちゃったりするユーザ定義関数ができてしまう。いいですねえ。