JSDBでデータベースを触る2007年05月09日 02時58分10秒

このままじゃ使いづらいってば。

本家のCookbookを見て、ちょっと試してみたところ、個人的にちょっと扱いづらかったのでいきなりTableクラスとRecordクラスを拡張することから始めてみた。

使いづらかった部分というのは、

  • Tableクラスで列情報にアクセスするのにtitleメソッド(カラム名の取得)、typeメソッド(型情報の取得)と分かれている
  • RecordクラスのコンストラクタがStringベースでちょっと面倒だった
といったあたりで、また行の抽出でループ処理が必須になるのでEnumerableにしてみることにした。以下はその拡張コード。prototype.jsが必要。
// Tableクラスの拡張
Object.extend( Table.prototype, {
	_each : function(iterator) {
		for(var i = 1; i <= this.count; i++) {
			iterator( this.getRow( i ) );
		}
	},
	// カラム名を配列で取得する
	colNames : function() {
		return this.getColumnInfo().map( function( col ) { return col.name; } );
	},
	// カラム情報の配列を取得する。orderは列位置、nameはカラム名、typeは型情報
	getColumnInfo : function() {
		var result = [];
		for(var i = 1; i <= this.colCount; i++) {
			result.push( {
				order : i,
				name : this.title( i ),
				type : this.type( i - 1 ).toArray().join("")
			} );
		}
		return result;
	}
} );
Object.extend( Table.prototype, Enumerable );

// Recordクラスの拡張
Object.extend( Record.prototype, {
	// 名前:値形式の単純なオブジェクトを返す
	toHash : function() {
		var result = {};
		for(var i = 0; i < this.count; i++) {
			result[ this.name( i ) ] = this.value( i );
		}
		return result;
	}
} );

// オブジェクトをパラメータにとってRecordを作成するファクトリメソッド
Record.fromHash = function(hash) {
	var src = $H( hash ).map( function(entry) {
		return [ entry.key, "=", entry.value == null ? "NULL" : entry.value ].join("");
	} ).join(",");
	return new Record( src );
}

じゃあ使ってみるか

このような拡張をした上で、データベースへアクセスしてみる。ここではmdbを使用してみた。

適当なmdbファイルを「test_db」としてODBCデータソース(ユーザDSNまたはシステムDSN)に登録しておいて、以下のようなコードでテーブルの作成、行の挿入、行の取得を行う。

js>var odbc = new ODBC("DSN=test_db")
js>odbc.exec("create table t_test ( id integer primary key, name text )")
true
js>var updater = new Table("odbc://test_db/t_test");
js>updater.add( Record.fromHash( { id : 1, name : "test 1" } ) )
-1
js>updater.add( Record.fromHash( { id : 2, name : "test 2" } ) )
-1
js>var table = odbc.query( "select * from t_test" );
js>table.each( function(record) {
2:      writeln( $H( record.toHash() ).inspect() )
3: } )
#<Hash:{'id': '1', 'name': 'test 1'}>
#<Hash:{'id': '2', 'name': 'test 2'}>

js>table.close()
true
js>updater.close()
true
js>odbc.close()
true
js>

まずは、「new ODBC()」でODBCオブジェクトを初期化する。この例ではmdbを使用したためユーザID・パスワードはないが、通常のDBMSの場合は「UID=ユーザID;PWD=パスワード」を追加する必要がある。

次のODBC#execでテスト用のテーブルを作成している。insert/delete/updateの場合もexecメソッドで実行する。

次の変数「updater」は今作成したテーブルの更新に使用するTableオブジェクト。この後に説明するODBC#queryメソッドの戻りもTableオブジェクトだが、それは読み取り専用らしく、更新する場合はこの例のようにURIをパラメータにしてTableをnewする必要がある。

その後はTable#addメソッドで行を新規に追加しているが、追加する行の初期化には、このエントリで拡張したRecrd::fromHashメソッドを使用している。このような拡張をしない場合は、
updater.add( new Record( "id=1,name=test 1" ) );
のようになる。

次に、ODBC#queryを使用してupdaterとは別にTableを取得している。この「table」は読み取り専用でaddメソッドは失敗する。

取得したtableをeachで列挙し、Record#toHashをHashにした上でinspectしてダンプしている。

最後に使用したTableとODBCをcloseして終了。

問題がちらほら

上記のサンプル程度では特に問題がないが、とりあえず目に付いた問題点をば。

  • Table#typeの戻り値の型がドキュメントと違う。type(1)のように引数を1つだけの場合はStringが帰ってくるはずだが実際は要素が1つのArrayが帰ってくる。
  • Table#typeで型情報は取得できるが、Record#valueで実際に取得する値は常にString
  • Table#addでレコードを追加すると、日本語のデータが化ける。insertクエリを使用した場合は化けない
  • Table#close、ODBC#closeを実行しても実際は接続が残っているぽい。mdbやSQLiteはjsdbを終了するまでファイル自体がロックされている
といった感じ。まあ、Table#typeはたいした話ではないが、日本語のデータが通らないとなるとこのオブジェクトモデルを利用したデータアクセスはほぼ使えないと思うのだが。

オブジェクトモデルが微妙に使いづらかったり、同じ情報を示すプロパティが複数あったり、あるオブジェクトの生成方法が複数あったり、設計も実装もちょっと中途半端な感じがする。特にODBC#queryで生成したTableでデータを更新できないのはなんだかなぁと思う。

おまけで、TableにRecordを生成するファクトリメソッド(Table#createRow、とかね)がほしかったなぁ。そのほうが新しいレコード挿入するのに勝手がよいんだけど。

コメント

_ mal ― 2007年05月09日 12時05分27秒

日本語は SpiderMonkey 本体がタコというか、JSDB が Unicode 関連の JS-API をきちんと使ってないですから。global.{encode,decode}* 関連使うとそこそこ何とかなるのがなんだかな。
設計・実装は基本的に adhoc & 力技っぽいので、中途半端なのは同感。でもちょっと工夫で何とかなっちゃうのは JS らしいというかなんというか。

_ dara-j ― 2007年05月09日 16時07分12秒

>JSDB が Unicode 関連の JS-API をきちんと使ってないですから。
あう。やはりそんな感じですか。VBSのInputBoxの戻りも化けるのでヤな予感はしたのですが。。。
ソースいじるスキルはないっす。

>でもちょっと工夫で何とかなっちゃうのは JS らしいというかなんというか。
だからJSは楽しいんですよね。

まぁ、DBまわりについてはクエリ実行で対処すれば実用になるのでよいかなと。バイナリ扱うわけじゃなし。

_ hiro ― 2007年05月11日 23時51分26秒

ソース見てみますよ。
JSDBかなり面白そうなんで、いろいろ触ってみます。
あと、作者に連絡して日本語ページ立ち上げようかと思ってます。

_ dara-j ― 2007年05月12日 01時27分27秒

hiroさん:
コメントどうもです。
>ソース見てみますよ。
うわ、ありがたや。なにか情報あったらぜひお願いします。

>作者に連絡して日本語ページ立ち上げようかと思ってます。
期待してます!
このブログの検索キーワードで一番多いのって「JSDB」なんですよ。関心もってる人は結構いると思うので、ぜひぜひお願いします。

_ hiro ― 2007年05月12日 06時43分28秒

ページ作りましたよ~
dara-jさんのblogをリンクさせて頂きました。
dara-jさん、一緒にJSDB関連の情報まとめませんか?
作者さんにも連絡を取りました。
dara-jさんにメールしたいんですが、どうしたらよいでしょう?!?!

_ dara-j ― 2007年05月12日 17時47分08秒

>一緒にJSDB関連の情報まとめませんか?
協力できることがあれば協力しますよ。とはいっても、たいした情報は提供できなそうですが。。

>dara-jさんにメールしたいんですが、どうしたらよいでしょう?!?!
gmailにアカ作りました。そちらでお願いします。

コメントをどうぞ

※メールアドレスとURLの入力は必須ではありません。 入力されたメールアドレスは記事に反映されず、ブログの管理者のみが参照できます。

※なお、送られたコメントはブログの管理者が確認するまで公開されません。

名前:
メールアドレス:
URL:
コメント:

トラックバック

このエントリのトラックバックURL: http://dara-j.asablo.jp/blog/2007/05/09/1495186/tb

※なお、送られたトラックバックはブログの管理者が確認するまで公開されません。