TL;DR:
Excluir
addslashes($data)
. É redundante aqui. Escape duplo .. duas vezes
$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data);
Você lê os dados, escapa como se fosse uma string literal e depois os converte em bytea octal ou escapes hexadecimais. Nunca poderia funcionar assim mesmo que
pg_escape_bytea
era são, o que não é. pg_escape_bytea
do PHP parece escape duplo a saída para que ela possa ser inserida em um literal de string. Isso é incrivelmente feio, mas não parece haver uma alternativa que não faça esse escape duplo, então você não pode usar instruções parametrizadas para bytea em PHP. Você ainda deve fazer isso para todo o resto. Neste caso, basta remover as
addslashes
linha para os dados lidos do arquivo é suficiente. Caso de teste mostrando que
pg_escape_bytea
escapes duplos (e sempre usa os antigos e ineficientes escapes octais também):<?php
# oh-the-horror.php
print pg_escape_bytea("Blah binary\x00\x01\x02\x03\x04 blah");
?>
Correr:
php oh-the-horror.php
Resultado:
Blah binary\\000\\001\\002\\003\\004 blah
Veja as barras invertidas duplas? Isso porque supõe que você vai interpolar isso no SQL como uma string, o que é extremamente ineficiente em memória, feio e um hábito muito ruim. Você não parece ter nenhuma alternativa, no entanto.
Entre outras coisas, isso significa que:
pg_unescape_bytea(pg_escape_bytea("\x01\x02\x03"));
... produz o resultado errado , uma vez que
pg_unescape_bytea
na verdade não é o inverso de pg_escape_bytea
. Também torna impossível alimentar a saída de pg_escape_bytea
em pg_query_params
como parâmetro, você deve interpolar. Decodificação
Se você estiver usando um PostgreSQL moderno, ele provavelmente configura
bytea_output
para hex
por padrão. Isso significa que se eu gravar meus dados em um bytea
field e, em seguida, buscá-lo de volta, será algo assim: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)
"Hum, o que", você pode dizer? Tudo bem, é apenas a representação hexadecimal um pouco mais compacta do PostgreSQL de
bytea
. pg_unescape_bytea
irá lidar com isso bem e produzir os mesmos bytes brutos como saída ... se você tiver um PHP moderno e libpq
. Em versões mais antigas, você receberá lixo e precisará definir bytea_output
para escape
para pg_unescape_bytea
para lidar com isso. O que você deve fazer em vez disso
Usar DOP.
Tem suporte sensato (ish) para
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();
Ver:
- PHP:Large Objects, que tem um exemplo de exatamente o que você quer;
- PDOStatement::bindParam
- como armazenar objeto serializado com namespace no banco de dados usando pdo php
- Vincule BYTEA à instrução preparada PGSQL PDO em PHP5
Você também pode querer dar uma olhada no suporte a lob (objeto grande) do PostgreSQL, que fornece uma interface de streaming e pesquisável que ainda é totalmente transacional.
Agora, vamos para minha caixa de sabão
Se o PHP tivesse uma distinção real entre os tipos "string de bytes" e "string de texto", você nem precisaria de
pg_escape_bytea
pois o driver do banco de dados pode fazer isso por você. Nada dessa feiúra seria necessário. Infelizmente, não existem tipos separados de string e bytes no PHP. Por favor, use PDO com instruções parametrizadas tanto quanto possível.
Onde você não puder, pelo menos use
pg_query_params
e instruções parametrizadas. addslashes
do PHP não é uma alternativa, é ineficiente, feio e não entende as regras de escape específicas do banco de dados. Você ainda precisa escapar manualmente de bytea
se você não estiver usando o PDO por motivos históricos nojentos, mas todo o resto deve passar por instruções parametrizadas. Para orientação sobre
pg_query_params
:- Tabelas Bobby, seção PHP.
- O manual do PHP em
pg_query_params