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できちゃったりするユーザ定義関数ができてしまう。いいですねえ。