Nucleus/SQLite

PostgreSQL

2006年3月17日

戯れに、PostgreSQLでもラッパーが作れそうかどうか、調べてみた。一番のポイントは、SQL Query中で使えるユーザ関数が定義できるかどうかである。

 調べると、有った有った、この機能が。ただ、SQLite の様にPHPの関数を呼び出せるわけではないらしい(SQLiteのように、直接PHPにバンドルされているわけではないので、あたりまえか)。これを記述するのは、ちょっと骨が折れるかも知れない。
 PostgreSQLのユーザ関数でphpが使えるツールも有るようだが、汎用的でないので、使えないだろう。
 どうやら一般的なのは、PL/pgSQL というプログラミング言語らしい。ローカルコンピューターにインストールしたPostgreSQLにも付いていた。パスカル系の言語のようである。

テーブルの作成に関しては、
MySQL:
CREATE TABLE `nucleus_item` (
`inumber` int(11) NOT NULL auto_increment,
`ititle` varchar(160) default NULL,
`ibody` text NOT NULL,
`imore` text,
`iblog` int(11) NOT NULL default '0',
`iauthor` int(11) NOT NULL default '0',
`itime` datetime NOT NULL default '0000-00-00 00:00:00',
`iclosed` tinyint(2) NOT NULL default '0',
`idraft` tinyint(2) NOT NULL default '0',
`ikarmapos` int(11) NOT NULL default '0',
`icat` int(11) default NULL,
`ikarmaneg` int(11) NOT NULL default '0',
PRIMARY KEY (`inumber`),
UNIQUE KEY `inumber` (`inumber`),
KEY `itime` (`itime`),
FULLTEXT KEY `ibody` (`ibody`,`ititle`,`imore`)
) TYPE=MyISAM PACK_KEYS=0;

pgSQL:
CREATE TABLE "nucleus_item" (
"inumber" serial NOT NULL PRIMARY KEY,
"ititle" varchar(160) default NULL,
"ibody" text NOT NULL,
"imore" text,
"iblog" int NOT NULL default '0',
"iauthor" int NOT NULL default '0',
"itime" timestamp NOT NULL default '1970-01-01 00:00:00',
"iclosed" smallint NOT NULL default '0',
"idraft" smallint NOT NULL default '0',
"ikarmapos" int NOT NULL default '0',
"icat" int default NULL,
"ikarmaneg" int NOT NULL default '0'
);
CREATE UNIQUE INDEX "inumber" ON "nucleus_item" ("inumber");
CREATE INDEX "itime" ON "nucleus_item" ("itime");
CREATE INDEX "ibody" ON "nucleus_item" ("ibody","ititle","imore");

これは、SQLite と殆ど変わらない。SQL クエリー構文の翻訳に関しては、SQLite 用の物に少し手を加えるだけで使えそうだ。ちなみに、使用できるデータ型は以下の通り
smailint / int2 2 バイト整数
integer / int / int4 4 バイト整数
bigint / int8 8 バイト整数
decimal(a, a) / numeric(a, s) 10 進型
real / float4 6 桁単精度浮動小数点
double precision / float8 15 桁倍精度浮動小数点
serial 4 バイト順序
bigserial 8 バイト順序
date 日付
time 時間
timestamp 日付時間
char(文字数) / character 固定長文字列 (最大 4096 文字)
varchar(文字数) / charcter varying 可変長文字列 (最大 4096 文字)
text 無制限テキスト
boolean / bool true / false


Nculeus 3.22 コアで使われいるMySQL関数。
mysql_affected_rows -- 一番最近の操作で変更された行の数を得る
pg_affected_rows -- 変更されたレコード(タプル)の数を返す
mysql_close -- MySQL 接続を閉じる
pg_close -- PostgreSQL接続を閉じる
mysql_connect -- MySQL サーバへの接続をオープンする
pg_connect -- PostgreSQL接続を開く
mysql_error -- 直近に実行された MySQL 操作のエラーメッセージを返す
pg_last_error -- 特定の接続から直近のエラーメッセージ文字列を取得する
pg_result_error -- 結果に関連するエラーメッセージを取得する 
mysql_fetch_array -- 連想配列、添字配列、またはその両方として結果の行を取得する
pg_fetch_array -- 行を配列として取得する
mysql_fetch_assoc -- 連想配列として結果の行を取得する
pg_fetch_assoc -- 行を配列として取得する
mysql_fetch_object -- 結果の行をオブジェクトとして取得する
pg_fetch_object -- 行をオブジェクトとして得る
mysql_fetch_row -- 結果を添字配列として取得する
pg_fetch_row -- 数字をインデックスとする配列として行を得る
mysql_field_name -- 結果において指定したフィールド名を取得する
pg_field_name -- フィールドの名前を返す
mysql_free_result -- 結果保持用メモリを開放する
pg_free_result -- メモリを開放する
mysql_insert_id -- 直近の INSERT 操作で生成された ID を得る
pg_last_oid -- 直近のオブジェクトIDを返す
mysql_num_fields -- 結果におけるフィールドの数を得る
pg_num_fields -- フィールド数を返す
mysql_num_rows -- 結果における行の数を得る
pg_num_rows -- 行数を返す
mysql_query -- MySQL クエリを送信する
//mysql_db_query -- MySQL クエリーを送信する
pg_query -- クエリを実行する
mysql_result -- 結果データを得る
pg_fetch_result -- 結果リソースから値を返す
mysql_select_db -- MySQL データベースを選択する
pg_connect -- PostgreSQL接続を開く

Nucleusコアでは使われいないMySQL関数
//mysql_unbuffered_query -- MySQL に SQL クエリを送信するが、結果に対してのフェッチやバッファリングは行わない
pg_query -- クエリを実行する
pg_free_result -- 結果保持用メモリを開放する
//mysql_client_encoding -- 文字セット名を返す
pg_client_encoding -- PostgreSQLクライアントのエンコーディングを取得する 
//mysql_data_seek -- 内部的な結果ポインタを移動する
pg_result_seek -- 結果リソースの内部レコード(行)オフセットを設定する
//mysql_errno -- 直近の MySQL 処理からエラーメッセージのエラー番号を返す
pg_result_status -- クエリ結果のステータスを取得する 
//mysql_escape_string -- mysql_query で使用するために文字列をエスケープする
//mysql_real_escape_string -- SQL 文中で用いる文字列の特殊文字をエスケープする
pg_escape_bytea -- bytea型にバイナリをエスケープする 
pg_escape_string -- テキスト/文字型用の文字列をエスケープする 
//mysql_create_db -- MySQL データベースを作成する
pg_query -- クエリを実行する
//mysql_pconnect -- MySQL サーバへの持続的な接続をオープンする
pg_pconnect -- 持続的なデータベース接続をオープンする
//mysql_fetch_field -- 結果からカラム情報を取得し、オブジェクトとして返す
pg_fetch_array -- 行を配列として取得する


うち、対応関数がまだ分からないもの。
//mysql_fetch_lengths -- 結果における各出力の長さを得る
//mysql_field_flags -- 結果において指定したフィールドのフラグを取得する
//mysql_field_len -- 指定したフィールドの長さを返す
//mysql_field_seek -- 結果ポインタを指定したフィールドオフセットにセットする
//mysql_field_table -- 指定したフィールドが含まれるテーブルの名前を取得する
//mysql_field_type -- 結果において指定したフィールドの型を取得する
//mysql_info -- 直近のクエリについての情報を得る
//mysql_list_fields -- MySQL テーブルのフィールドのリストを得る
//mysql_list_processes -- MySQL プロセスのリストを得る
//mysql_list_tables -- MySQL データベース上のテーブルのリストを得る
//mysql_stat -- カレントのシステム状況を得る
//mysql_tablename -- フィールドのテーブル名を得る
//mysql_thread_id -- カレントのスレッド ID を返す


MySQLでの対応関数がまだ分からないpgSQL関数
pg_cancel_query -- 非同期クエリを取り消す 
pg_connection_busy -- 接続がビジーかどうか調べる 
pg_connection_reset -- 接続をリセット(再接続)する 
pg_connection_status -- 接続ステータスを取得する 
pg_convert -- SQL命令として実行可能な形式の連想配列の値に変換する 
pg_copy_from -- 配列からテーブルをコピーする 
pg_copy_to -- 配列にテーブルをコピーする 
pg_dbname -- データベース名の取得
pg_delete -- レコードを削除する 
pg_end_copy -- PostgreSQLバックエンドに同期する
pg_fetch_all -- 取得されたすべての行を配列として取得
pg_field_is_null -- フィールドがNULLかどうか調べる
pg_field_num -- 指定されたフィールドのフィールド番号を返す
pg_field_prtlen -- 表示される長さを返す
pg_field_size -- 指定したフィールドの内部記憶領域におけるサイズを返す 
pg_field_type -- フィールド番号に対応する型名を返す 
pg_get_notify -- データベース接続にpingを行う
pg_get_pid -- データベース接続にpingを行う
pg_get_result -- 非同期クエリの結果を取得する 
pg_host -- ホスト名を返す
pg_insert -- テーブルに配列を挿入する 
pg_last_notice -- PostgreSQLサーバからの直近の通知メッセージを返す 
pg_lo_close -- ラージオブジェクトをクローズする
pg_lo_create -- ラージオブジェクトを生成する
pg_lo_export -- ラージオブジェクトをファイルにエクスポートする
pg_lo_import -- ファイルからラージオブジェクトをインポートする
pg_lo_open -- ラージオブジェクトをオープンする
pg_lo_read_all -- ラージオブジェクト全体を読み込みブラウザに直接送信する 
pg_lo_read -- ラージオブジェクトを読み込む
pg_lo_seek -- ラージオブジェクトの位置をシークする 
pg_lo_tell -- ラージオブジェクトのカレントの位置を返す 
pg_lo_unlink -- ラージオブジェクトを削除する
pg_lo_write -- ラージオブジェクトを書く
pg_meta_data -- テーブルからメタデータを取得する 
pg_options -- 接続に関連するオプションを取得する
pg_pconnect -- 持続的なデータベース接続をオープンする
pg_ping -- データベース接続を調べる
pg_port -- 接続に関連するポート番号を返す
pg_put_line -- NULLで終る文字列をPostgreSQLバックエンドに送信する 
pg_select -- レコードを選択する 
pg_send_query -- 非同期クエリを送信する 
pg_set_client_encoding -- PostgreSQLクライアントのエンコーディングを設定する 
pg_trace -- PostgreSQLサーバーへの接続をトレースする
pg_tty -- tty名を返す
pg_unescape_bytea -- bytea型のバイナリをアンエスケープする 
pg_untrace -- PostgreSQLサーバーへの接続のトレースを無効にする 
pg_update -- テーブルを更新する

コメント

Katsumi (2006年9月18日 12:56:53)

 PL/pgSQL は、プログラミング言語としてはPHPなどと比べると機能的にかなり劣る。かといって、PL/PHPを導入できるような環境であればMySQLだってインストールできるはずなので、PL/pgSQLでさまざまなことを行うことを考えるべきである。
 妥協策としては、クエリー処理を2段階で行うことが考えられる。かりに、ストアドファンクション名を TESTFUNC() とし、処理用のテンポラリテーブル TEMPTABLE が利用できるとする。

1)一段目の処理
 ここで TESTFUNC() が行う処理は、TEMPTABLE に自分の名前(TESTFUNC)および、関数が呼ばれたときの引数を保存するだけである。最後に、pg_free_result を行って、クエリー結果を破棄しメモリの開放を行う。
(TEMPTABLE が空のときは PL/pgSQL が呼ばれていないということなので、クエリー結果をそのまま返してすべて終了する。)

2)PHP を用いて関数処理
 次に、PHP で TEMPTABLE の内容を呼び出し、PHP のコードで処理し(sqlitequeryfunctions.php の関数郡がそのまま使える)、結果を TEMPTABLE に挿入する。

3)二段目の処理
 TESTFUNC() 内において、TEMPTABLE に保存された結果(上記、PHP で処理されたもの)を返し、関数を終了する。

コメント送信