墜落日記 - 2008年10月26日の墜落
PostgreSQL 抽象化
現在ゴリゴリと書いている PHP のライブラリ Ag:PURE 2.0 では、従来から目立たぬように出しゃばらぬようにの基本原則を守りつつ、より環境としての側面を出すように実装している。
使う気があるのならテンプレートエンジンから簡易 MVC フレームワーク、より高度なセッション管理まで色々と用意している。
使う気がないのならコアのパッケージ処理機構と例外処理機構だけ利用して、その他のは自分のやりたいようにやることも出来る。
(それらすら要らないなら Ag:PURE 自体が要らない)
そんな中で、現在勤しんでいるのはデータベース抽象化ライブラリの PostgreSQL 実装。
なんで今更にデータベース抽象化ライブラリを作っているのかという話しもあるかもしれないが、なんちゅ~か PDO では Oracle が BUGGY だからである。
(PDO の Oracle ドライバのバグに関しては後述)
で、PostgreSQL なのになんで Oracle と関係するのかというと、次のプロジェクトで Oracle と PostgreSQL が同居するからである(爆)
PDO だと Oracle が使えないからと PostgreSQL だけ PDO 使って Oracle は OCI8 関数で、なんてやるとデータベースの接続先を意識してコードを変えなければならないが、これは避けたい。
かといって、データベース抽象化だけ PEAR を利用するのもアンバランス。
で、一念発起して Ag:PURE にデータベース抽象化ライブラリを突っ込んでしまおうと相成ったわけである。
Oracle 実装は元々やっていたので技術的な蓄積もあり、問題なく実装完了。
PostgreSQL 実装に関しては、抽象化ライブラリが更に抽象化した PDO を呼ぶというのも間抜けなので、PostgreSQL 関数を直接利用することにして、PostgreSQL 関数を改めて試してみる。
(現在の Arcadian garden はバックエンドが PostgreSQL だが PDO で構成しているので、PostgreSQL 関数を直接利用するのは初めて)
関数の構成は OCI8 関数とあまり変わらないが、かなり発想が違うのがプリペアードステートメントの実装の仕方かな?
OCI8 がプレースホルダを名前解決できたりするのと違い、PostgreSQL の方は連番でしか指定できない。
PostgreSQL の PREPARE 文と EXECUTE 文をそのまま利用しているのが原因と思われるが、流石にこれは OCI8 風の名前解決が出来る状態に隠蔽しないといけないな………
双方共に隠蔽したいのは日付の管理。
日付の管理は言語や実装毎にその実現方法が異なる特にややこしい部分だが、これを PHP との親和性が高い UNIX EPOCH による管理と透過的にしたい。
学術計算を想定していないので極端に大きい精度は要らないし、単純な管理でよいのである。
(整数は 32bit 精度しか扱えない PHP で UNIX EPOCH となると 2038 年問題とか起こりそうだが)
その他、ラージオブジェクトの取り扱いやなんかは現在想定にないのでオミット。
さてさて、構想が色々とあって実装時間が足りないとか、突貫工事でコーディングしているのでテストが間に合うかとか、そもそもドキュメント書いてる時間在るのか? とか疑問もあるが、取り敢えず形にしないと………
PDO の Oracle ドライバのバグに関してだが。
どうも現在の PDO の Oracle ドライバは、例えばデータベースの文字セットが JA16SJIS で、クライアントの文字セットが AL32UTF8 だったりするとバッファオーバフローが起こる可能性があるらしい。
これは文字列の転送時にデータベースのデータ型の桁数に対してクライアント側のバッファを用意してしまうためと思われる。
前述の通り、サーバ側文字セットが JA16SJIS でカラム型が VARCHAR2(30) だとして、クライアント側が AL32UTF8 だとする。
この時、全角 10 文字で格納されているまでは O.K. なのだが、11 文字になるとエラーになる。
AL32UTF8 で全角 10 文字は 30 バイトだが、全角 11 文字だと 33 バイトで、データ型の桁数を超えてしまうためだ。
この問題は OCI8 関数を直接利用することで回避できる。
Ag:PURE 1.0 で OCI8 用にクラスライブラリが組まれているのはこのためだ。
………このバグ、年単位で放置されていたようだが誰も気付かないんだろうか………?
コメントは投稿されていません。