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マニュアル