NpgSql - 从具有解码功能的查询返回的错误数据

NpgSql - bad data returned from query with decode function

我目前正在开始将应用程序的 postgres 8.4 db 升级到 9.4 的过程。实际的数据库迁移已经完美地进行了,但是当 运行 针对 9.4 数据库时,一些应用程序查询没有 returning 奇怪的结果。我正在为 C# 使用 NpgSql v2.0.12.0 库。该问题似乎与存储编码为 base64 字符串的文本数据的几个表有关。查询调用 postgres 解码函数,以便 return 将编码数据作为纯文本。例如:

  SELECT
     decode(user_name, 'base64')::text as user_name
   FROM
     login
   WHERE
     login_id = 123;

当提交到 8.4 数据库时,字符串被正确地returned 到应用程序。当提交到 9.4 数据库时,我得到

\x61646d696e6973747261746f72

在 PgAdmin SQL 工具中,两种情况下的结果都是正确的。我确定这可能是某种编码问题,但对于我的生活我无法弄清楚 - 我已经用谷歌搜索了几个小时,翻阅了 postgres 文档并在这里无休止地搜索但最终未能找到解决我的问题。希望有一些 PostGres 人可以指出正确的方向来解决这个问题。

您一直依赖于将 bytea 输出解释为当前编码中的字符串,即您的代码一直存在错误,但碰巧有效。

较早的 PostgreSQL 版本使用 "escape" bytea 文字格式,对于 7 位 ASCII 字符看起来像纯文本,并且对不可打印和 8 位字符使用八进制转义,例如

test=> SET bytea_output = 'escape';
SET
test=> SELECT convert_to('administrator á
', 'utf-8');
         convert_to         
----------------------------
 administrator 312
(1 row)

更高版本的 PostgreSQL 版本默认为 'hex' 输出,它将 所有内容 编码为十六进制:

test=> SET bytea_output = 'hex';
SET
test=> SELECT convert_to('administrator á
', 'utf-8');
              convert_to              
--------------------------------------
 \x61646d696e6973747261746f7220c3a10a
(1 row)

因此您的应用无法再假设 bytea 是文本。

如果 base64 字符串是当前本地文本编码中的有效文本,您可以使用 convert_from(decode(user_name, 'base64'), 'utf-8')。但在那种情况下,您应该首先将其存储为正常 text 而不是 base64 编码。

如果 base64 字符串在当前编码中无效,例如它包含空字节、无法在 client_encoding 中表示的字符等,那么您应该 return 十六进制或 base64 表示并在客户端应用程序中对其进行解码。