TL;博士:
删除addslashes($data)
。这里是多余的。
双重转义..两次
$data=fread($p,filesize($fi));
$data=addslashes($data);
$dat= pg_escape_bytea($data);
您读取数据,将其转义为字符串文字,然后将其转换为 bytea 八进制或十六进制转义。即使pg_escape_bytea
是理智的,它也永远不会那样工作,但事实并非如此。
PHPpg_escape_bytea
似乎对输出进行了双重转义,因此可以将其插入字符串文字中。这非常难看,但似乎没有不做这种双重转义的替代方案,因此您似乎无法在 PHP 中对 bytea 使用参数化语句。对于其他所有事情,您仍然应该这样做。
在这种情况下,只需删除addslashes
从文件中读取的数据行就足够了。
显示双重转义的测试用例pg_escape_bytea
(并且总是使用旧的、低效的八进制转义):
<?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
into的输出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
. pg_unescape_bytea
将处理它并产生与输出相同的原始字节......如果你有一个现代 PHP 和libpq
. 在旧版本上,你会得到垃圾,需要设置bytea_output
为escape
forpg_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();
看:
您可能还想查看 PostgreSQL 的 lob(大对象)支持,它提供了一个仍然完全事务性的流式、可搜索接口。
现在,到我的肥皂盒上
如果 PHP 在“字节字符串”和“文本字符串”类型之间有真正的区别,那么您甚至不需要pg_escape_bytea
,因为数据库驱动程序可以为您做到这一点。不需要这些丑陋的东西。不幸的是,PHP 中没有单独的字符串和字节类型。
请尽可能使用带有参数化语句的 PDO。
在你不能的地方,至少使用pg_query_params
和参数化的语句。PHPaddslashes
不是替代品,它效率低下、丑陋,并且不理解数据库特定的转义规则。如果您出于不良的历史原因不使用 PDO,您仍然必须手动转义bytea
,但其他一切都应通过参数化语句。
有关以下方面的指导pg_query_params
: