PostgreSQL
 sql >> Teknologi Basis Data >  >> RDS >> PostgreSQL

Menyimpan gambar dalam bidang byte dalam database PostgreSQL

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


  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Kembalikan daftar yang dikelompokkan dengan kemunculan menggunakan Rails dan PostgreSQL

  2. Cara mengatur nilai bidang variabel komposit menggunakan SQL dinamis

  3. Bagaimana Mod() Bekerja di PostgreSQL

  4. PostgreSQL 11:Peninjau Patch untuk Mempartisi Patch

  5. cara memperbaiki OperationalError:(psycopg2.OperationalError) server menutup koneksi secara tidak terduga