sql >> Databáze >  >> RDS >> PostgreSQL

Ukládání obrázků do polí bajtů v databázi PostgreSQL

TL;DR:

Smažte addslashes($data) . Tady je to nadbytečné.

Dvojité escapování .. dvakrát

$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data); 

Načtete data, uzavřete je, jako by to byl řetězcový literál, a poté je převedete na bajtové osmičkové nebo hex. Takto by to nikdy nemohlo fungovat, i kdyby pg_escape_bytea byl příčetný, což není.

pg_escape_bytea PHP vypadá jako dvojitý únik výstup, takže jej lze vložit do řetězcového literálu. To je neuvěřitelně ošklivé, ale nezdá se, že by existovala alternativa, která by toto dvojité escapování neprováděla, takže se zdá, že v PHP nemůžete používat parametrizované příkazy pro bytea. Stejně byste to měli udělat pro všechno ostatní.

V tomto případě jednoduše odstraňte addslashes řádek pro data načtená ze souboru je dostačující.

Testovací případ ukazuje, že pg_escape_bytea double-escapes (a vždy také používá staré, neefektivní oktalové escape):

<?php
# oh-the-horror.php
print pg_escape_bytea("Blah binary\x00\x01\x02\x03\x04 blah");
?>

Spustit:

php oh-the-horror.php

Výsledek:

Blah binary\\000\\001\\002\\003\\004 blah

Vidíte zdvojená zpětná lomítka? Je to proto, že se předpokládá, že jej budete interpolovat do SQL jako řetězec, což je extrémně paměťově neefektivní, ošklivé a velmi špatný zvyk. Zdá se však, že nemáte žádnou alternativu.

Mimo jiné to znamená, že:

pg_unescape_bytea(pg_escape_bytea("\x01\x02\x03"));

... vytváří nesprávný výsledek , protože pg_unescape_bytea není ve skutečnosti opakem pg_escape_bytea . Také to znemožňuje napájet výstup pg_escape_bytea do pg_query_params jako parametr jej musíte interpolovat.

Dekódování

Pokud používáte moderní PostgreSQL, pravděpodobně nastavuje bytea_output na hex ve výchozím stavu. To znamená, že když zapíšu svá data do bytea pole a poté jej načtěte zpět, bude to vypadat nějak takto:

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)

"Ehm, co," dalo by se říct? To je v pořádku, je to jen trochu kompaktnější hexová reprezentace bytea PostgreSQL . pg_unescape_bytea zvládne to dobře a vytvoří stejné nezpracované bajty jako výstup ... pokud máte moderní PHP a libpq . Na starších verzích budete mít odpadky a budete muset nastavit bytea_output k escape pro pg_unescape_bytea zvládnout to.

Co byste měli udělat místo toho

Použijte CHOP.

Má rozumnou podporu pro 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();

Viz:

  • PHP:Velké objekty, které obsahují příklad toho, co přesně chcete;
  • PDOStatement::bindParam
  • jak uložit serializovaný objekt s jmenným prostorem v databázi pomocí pdo php
  • Navázat BYTEA na PGSQL připravený příkaz PDO v PHP5

Můžete se také podívat na podporu lob (velký objekt) PostgreSQL, která poskytuje streamované rozhraní, které je stále plně transakční.

A teď k mé mýdlové krabičce

Pokud by PHP skutečně rozlišovalo mezi typy "byte string" a "text string", nepotřebovali byste ani pg_escape_bytea jak by to za vás mohl udělat ovladač databáze. Nic z této ošklivosti by nebylo potřeba. Bohužel v PHP neexistují žádné samostatné typy řetězců a bajtů.

Prosím, používejte PDO s parametrizovanými příkazy co nejvíce.

Kde nemůžete, použijte alespoň pg_query_params a parametrizované příkazy. addslashes PHP není alternativou, je neefektivní, ošklivý a nerozumí pravidlům útěku specifickým pro databázi. Stále musíte ručně escapovat bytea pokud nepoužíváte PDO z historických důvodů, ale vše ostatní by mělo projít parametrizovanými příkazy.

Pokyny k pg_query_params :

  • Tabulky Bobby, sekce PHP.
  • Příručka PHP o pg_query_params


  1. Co je SQL a jak s ním začít?

  2. Sdružování připojení PostgreSQL:Část 3 – Pgpool-II

  3. mysql trigger uložený trigger je již používán příkazem, který vyvolal uložený trigger

  4. Jak upgradovat z MariaDB 10.4 na MariaDB 10.5