Data::Model PostgreSQL 対応作業中

http://github.com/fujiwara/p5-Data-Model/tree/master

Data::Model を PostgreSQL でも使いたいので対応作業をやってみたら、テストまわりでいくつか困ったことが。

  • テーブル名 user は PostgreSQL では予約語のため、quote しないと使えない
    • quote すればいいのだけど、PostgreSQL は "", SQLiteMySQL は `` で、そこを切り替えるのが面倒そうだったので s/user/tusr/g; してしまった
  • CHAR 型のカラムは、PostgreSQL では末尾に空白が埋められるので、取り出すと期待する値と異なる (MySQL では取り出すときに切り捨てられる)
    • デフォルトの型を切り替えられるように Schema::Properties->default_column_type を追加
    • テスト内で明示的に CHAR(100) としているのは VARCHAR(100) に変更

今のところ t/020_mock/dbi-pg-basic.t が通るところまで。
ひととおり t/020_mock/dbi-pg-*.t が成功するところまでできたので push した。

やってて気がついた PostgreSQLMySQL, SQLite の差異。

auto increment (Pg では SERIAL 型) のカラムに明示的に NULL を入れようとすると、MySQL では auto increment された値が設定されるが、Pg では not-null constraint エラー。

CREATE TABLE foo ( id SERIAL PRIMARY KEY, bar text );
INSERT INTO foo ( bar ) VALUES ( 'BAR' );            -- OK
INSERT INTO foo ( id, bar ) VALUES ( NULL, 'BAR' );  -- NG

http://github.com/fujiwara/p5-Data-Model/commit/02b5e41f37f9dacf5a3637887415f0547a4db5db

auto increment のカラムに値が指定されて INSERT された場合は last_insert_id が取れない。
nextval() が呼ばれてないから。仮にそのセッションの別の SQL で nextval() されていた場合、そっちの値を読み取ってしまう可能性があるので、まずい。
http://github.com/fujiwara/p5-Data-Model/commit/1e3e296c59c5077628843af776a722a48341fc99