TL;DR:
Hapus addslashes($data)
. Ini berlebihan di sini.
Double-escape .. dua kali
$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data);
Anda membaca data di dalamnya, menghindarinya seolah-olah itu adalah string literal, lalu mengubahnya menjadi byte oktal atau hex lolos. Itu tidak akan pernah bisa bekerja seperti itu bahkan jika pg_escape_bytea
itu waras, padahal tidak.
pg_escape_bytea
PHP tampaknya melarikan diri ganda output sehingga dapat dimasukkan ke dalam string literal. Ini sangat jelek, tetapi tampaknya tidak ada alternatif yang tidak melakukan pelolosan ganda ini, jadi Anda sepertinya tidak dapat menggunakan pernyataan berparameter untuk byte di PHP. Anda tetap harus melakukannya untuk yang lainnya.
Dalam hal ini, cukup hapus addslashes
baris untuk data yang dibaca dari file sudah cukup.
Kasus uji menunjukkan bahwa pg_escape_bytea
double-escapes (dan selalu menggunakan octal escape yang lama dan tidak efisien juga):
<?php
# oh-the-horror.php
print pg_escape_bytea("Blah binary\x00\x01\x02\x03\x04 blah");
?>
Jalankan:
php oh-the-horror.php
Hasil:
Blah binary\\000\\001\\002\\003\\004 blah
Lihat garis miring terbalik dua kali lipat? Itu karena dengan asumsi Anda akan menginterpolasinya ke dalam SQL sebagai string, yang sangat tidak efisien memori, jelek, dan kebiasaan yang sangat buruk. Namun, Anda tampaknya tidak mendapatkan alternatif apa pun.
Antara lain ini berarti bahwa:
pg_unescape_bytea(pg_escape_bytea("\x01\x02\x03"));
... menghasilkan hasil yang salah , sejak pg_unescape_bytea
sebenarnya bukan kebalikan dari pg_escape_bytea
. Itu juga tidak memungkinkan untuk memberi makan output pg_escape_bytea
ke dalam pg_query_params
sebagai parameter, Anda harus menginterpolasinya.
Dekode
Jika Anda menggunakan PostgreSQL modern, ini mungkin menetapkan bytea_output
ke hex
secara default. Itu berarti jika saya menulis data saya ke bytea
bidang lalu ambil kembali, itu akan terlihat seperti ini:
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)
"Um, apa", katamu? Tidak apa-apa, hanya saja representasi hex PostgreSQL yang sedikit lebih ringkas dari bytea
. pg_unescape_bytea
akan menanganinya dengan baik dan menghasilkan byte mentah yang sama dengan output ... jika Anda memiliki PHP modern dan libpq
. Pada versi yang lebih lama Anda akan mendapatkan sampah dan perlu mengatur bytea_output
untuk escape
untuk pg_unescape_bytea
untuk menanganinya.
Apa yang harus Anda lakukan sebagai gantinya
Gunakan PDO.
Ini memiliki dukungan waras(ish) untuk 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();
Lihat:
- PHP:Objek Besar, yang memiliki contoh persis seperti yang Anda inginkan;
- Pernyataan PDO::bindParam
- cara menyimpan objek serial dengan namespace di database menggunakan pdo php
- Mengikat BYTEA ke PGSQL PDO Pernyataan yang Disiapkan di PHP5
Anda mungkin juga ingin melihat dukungan lob (objek besar) PostgreSQL, yang menyediakan antarmuka streaming dan dapat dicari yang masih sepenuhnya transaksional.
Sekarang, ke kotak sabun saya
Jika PHP memiliki perbedaan nyata antara tipe "byte string" dan "text string", Anda bahkan tidak perlu pg_escape_bytea
karena driver database dapat melakukannya untuk Anda. Tak satu pun dari keburukan ini akan diperlukan. Sayangnya, tidak ada tipe string dan byte yang terpisah di PHP.
Harap gunakan PDO dengan pernyataan berparameter sebanyak mungkin.
Jika tidak bisa, setidaknya gunakan pg_query_params
dan pernyataan berparameter. addslashes
PHP bukan alternatif, tidak efisien, jelek, dan tidak memahami aturan pelolosan khusus basis data. Anda masih harus secara manual keluar dari bytea
jika Anda tidak menggunakan PDO karena alasan historis yang buruk, tetapi yang lainnya harus melalui pernyataan berparameter.
Untuk panduan tentang pg_query_params
:
- Tabel bobby, bagian PHP.
- Manual PHP di
pg_query_params