postgres 字节数组转义在红宝石中是否损坏?



简单的例子:

Zlib::Inflate.inflate(PG::Connection.unescape_bytea(PG::Connection.escape_bytea(Zlib::Deflate.deflate('["128,491,128,487"]'))))
Zlib::DataError: incorrect data check

这不是 zlib 的问题,因为以下成功:

Zlib::Inflate.inflate(Zlib::Deflate.deflate('["128,491,128,487"]'))
=> "["128,491,128,487"]"

解析失败/成功取决于提供的字符串:

Zlib::Inflate.inflate(PG::Connection.unescape_bytea(PG::Connection.escape_bytea(Zlib::Deflate.deflate('["128,491,128,487", "128,491,128,490", "38,465,40,463"]'))))
=> "["128,491,128,487", "128,491,128,490", "38,465,40,463"]"

是我做错了什么,还是红宝石中逃逸的后场坏了?我能做什么作为替代方案?

试穿:红宝石 2.2.3p173,宝石 pg-0.18.4;红宝石 2.4.1p111,宝石 pg-0.21.0

来自 https://bitbucket.org/ged/ruby-pg/issues/262/postgres-bytearray-escaping 的答案:

(un(escape_bytea的描述具有误导性。它彼此并不完全相反。

PG::Connection.escape_bytea 使用旧的和已弃用的转义机制,该机制必须进行双重转义 - 首先作为 BYTEA 进行转义,次要作为字符串文字(在字符串前后添加 '(以插入到 SQL 字符串中。出于方便和性能原因,这是一步完成的。

相反,PG::Connection.unescape_bytea 只对 BYTEA 进行转义,因为它旨在解码查询检索到的列数据。此数据不会作为字符串文本进行转义。 您现在有两个选项可以使上述工作:

enco = PG::TextEncoder::Bytea.new
deco = PG::TextDecoder::Bytea.new
Zlib::Inflate.inflate(deco.decode(enco.encode(Zlib::Deflate.deflate('["128,491,128,487"]'))))

这使用了 pg gem 的类型编码器而不是 libpq。编码器使用较新的BYTEA逃避机器主义,并且比libpq的功能快一点。这仍然独立于服务器连接。 conn = PG.connect

Zlib::Inflate.inflate(conn.unescape_bytea(conn.escape_bytea(Zlib::Deflate.deflate('["128,491,128,487"]'))))

这利用了 libpq 的连接绑定转义函数。它们还使用较新的转义机制,因此不会发生双重转义。

最新更新