TL; DR:
addslashes($data)を削除します 。ここでは冗長です。
ダブルエスケープ..2回
$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data);
データを読み込んで、文字列リテラルであるかのようにエスケープしてから、8進数または16進数のエスケープに変換します。 pg_escape_byteaであっても、そのように機能することはありません。 正気でしたが、そうではありません。
PHPのpg_escape_bytea 二重エスケープのように見える 文字列リテラルに挿入できるように出力します。これは信じられないほど醜いですが、この二重エスケープを行わない代替手段はないようです。そのため、PHPでbyteaのパラメーター化されたステートメントを使用することはできないようです。それでも、他のすべてについてはそうする必要があります。
この場合、addslashesを削除するだけです。 ファイルから読み込まれたデータの行で十分です。
pg_escape_byteaを示すテストケース ダブルエスケープ(そして常に古くて非効率的な8進数エスケープも使用します):
<?php
# oh-the-horror.php
print pg_escape_bytea("Blah binary\x00\x01\x02\x03\x04 blah");
?>
実行:
php oh-the-horror.php
結果:
Blah binary\\000\\001\\002\\003\\004 blah
二重の円記号が表示されますか?これは、SQLに文字列として補間することを想定しているためです。これは、メモリ効率が非常に低く、醜く、非常に悪い習慣です。ただし、代替手段はないようです。
とりわけ、これは次のことを意味します:
pg_unescape_bytea(pg_escape_bytea("\x01\x02\x03"));
...間違った結果が生成されます 、pg_unescape_bytea以降 実際にはpg_escape_byteaの逆ではありません 。また、pg_escape_byteaの出力をフィードすることもできなくなります。 pg_query_paramsに パラメータとして、それを補間する必要があります。
デコード
最新のPostgreSQLを使用している場合は、おそらくbytea_outputが設定されます。 hexへ デフォルトでは。つまり、データをbyteaに書き込むと フィールドをフェッチして戻すと、次のようになります。
craig=> CREATE TABLE byteademo(x bytea);
CREATE TABLE
craig=> INSERT INTO byteademo(x) VALUES ('Blah binary\\000\\001\\002\\003\\004 blah');
INSERT 0 1
craig=> SELECT * FROM byteademo ;
x
----------------------------------------------------------------------------
\x426c61682062696e6172795c3030305c3030315c3030325c3030335c30303420626c6168
(1 row)
「ええと、何」と言うかもしれませんか?それは問題ありません。PostgreSQLのbyteaのわずかにコンパクトな16進表現です。 。 pg_unescape_bytea それをうまく処理し、出力と同じ生のバイトを生成します...最新のPHPとlibpqを使用している場合 。古いバージョンではゴミが出て、bytea_outputを設定する必要があります escapeする pg_unescape_byteaの場合 それを処理します。
代わりにすべきこと
PDOを使用します。
byteaを適切にサポートしています 。
$sth = $pdo->prepare('INSERT INTO mytable(somecol, byteacol) VALUES (:somecol, :byteacol)');
$sth->bindParam(':somecol', 'bork bork bork');
$sth->bindParam(':byteacol', $thebytes, PDO::PARAM_LOB);
$sth->execute();
参照:
- PHP:ラージオブジェクト。必要なものの正確な例があります。
- PDOStatement ::bindParam
- pdophpを使用して名前空間を持つシリアル化されたオブジェクトをデータベースに保存する方法
- BYTEAをPHP5のPGSQLPDOプリペアドステートメントにバインドする
また、PostgreSQLのlob(ラージオブジェクト)サポートを調べることもできます。これは、完全にトランザクションであるストリーミングのシーク可能なインターフェイスを提供します。
さて、私の石鹸箱に行きましょう
PHPで「バイト文字列」タイプと「テキスト文字列」タイプが実際に区別されている場合は、pg_escape_byteaも必要ありません。 データベースドライバがあなたのためにそれをすることができるので。この醜さは必要ありません。残念ながら、PHPには個別の文字列とバイトのタイプはありません。
可能な限り、パラメータ化されたステートメントでPDOを使用してください。
できない場合は、少なくともpg_query_paramsを使用してください およびパラメータ化されたステートメント。 PHPのaddslashes 代替手段ではなく、非効率的で醜く、データベース固有のエスケープルールを理解していません。 byteaを手動でエスケープする必要があります 歴史的な理由でPDOを使用していないが、それ以外はすべてパラメーター化されたステートメントを実行する必要がある場合。
pg_query_paramsのガイダンス :
- ボビーテーブル、PHPセクション。
-
pg_query_paramsに関するPHPマニュアル