スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

PHPでPostgreSQLの配列型を受ける

PostgreSQLでは配列型という型があるのですが、PHPで使ってみるとどうなるのか調べてみました。
DBの接続方法はZend_Dbを使いました。PDOのラッパーなのでPDOでも同じ動きかと思います。
まず、SQLです。
DROP TABLE IF EXISTS t_test;
CREATE TABLE t_test (
id BIGINT
,value TEXT[]
,val INTEGER[]
);

INSERT INTO t_test (id, value, val) VALUES
(1, ARRAY['a,b"c', e'e\\f"g', 'h}ij'], ARRAY[1, 2, 3])
,(2,ARRAY['', '123', '456', '789', ''], ARRAY[4, 5, 6])
;

まず、単純にselect文を流してみます。
<?php
require_once 'Zend/Db.php';
require_once 'Zend/Config/Ini.php';

$config = new Zend_Config_Ini('config.ini');
$db = Zend_Db::factory($config->
db);

$stmt = $db->query("select * from t_test");
$res = $stmt->fetchAll();
var_dump($res);

config.iniは以下の通り。
db.adapter = pdo_pgsql
db.params.host = localhost
db.params.username = user
db.params.password = password
db.params.dbname = test

実行結果は以下の通りです。
array(2) {
[0]=>
array(3) {
["id"]=>
int(1)
["value"]=>
string(27) "{"a,b\"c","e\\f\"g","h}ij"}"
["val"]=>
string(7) "{1,2,3}"
}
[1]=>
array(3) {
["id"]=>
int(2)
["value"]=>
string(19) "{"",123,456,789,""}"
["val"]=>
string(7) "{4,5,6}"
}
}

valueの方はエスケープとか検証するためわかりにくいのですが、valの方を見ればわかりやすいと思いますが、配列型は文字列で返すようです。波括弧でくくられ、カンマで区切られているようです。
これを、文字列の配列として扱いたいのですがvalueを見るとわかるように、単純にカンマで区切ればよいわでけはないようです。
そこで、一次元配列のみですが、解析する関数を作りました。
function pgstr2ary($src) {
$src = preg_replace('/^\{|\}$/u', '', $src);
$ary = preg_split('//u', $src, -1, PREG_SPLIT_NO_EMPTY);

$quote = false;
$escape = false;
$result = array();
$value = "";
$setted = true;
foreach ($ary as $item) {
if ('"' === $item) {
if ($quote) {
if ($escape) {
$value .= $item;
} else {
$quote = false;
$setted = false;
}
} else {
$quote = true;
}
} else if ("\\" === $item) {
if ($escape) {
$escape = false;
$value .= $item;
} else {
$escape = true;
}
} else if (',' === $item) {
if ($quote) {
$value .= $item;
} else {
$result[] = $value;
$value = "";
$setted = true;
}
} else {
$value .= $item;
}

// エスケープ以外の時はエスケープの解除
if ("\\" !== $item) {
$escape = false;
}
}
if (("" !== $value) || (!$setted)) {
$result[] = $value;
}

return $result;
}

これを使ってみた結果が以下の通りです。
array(3) {
[0]=>
string(5) "a,b"c"
[1]=>
string(5) "e\f"g"
[2]=>
string(4) "h}ij"
}
array(5) {
[0]=>
string(0) ""
[1]=>
string(3) "123"
[2]=>
string(3) "456"
[3]=>
string(3) "789"
[4]=>
string(0) ""
}
スポンサーサイト

COMMENTS

COMMENT FORM

TRACKBACK


この記事にトラックバックする(FC2ブログユーザー)

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。