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

时间:2015-12-02 21:29:44

标签: c# postgresql encoding npgsql

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

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

当提交到8.4 DB时,字符串将正确返回给应用程序。当提交到9.4 DB我得到

\x61646d696e6973747261746f72

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

1 个答案:

答案 0 :(得分:1)

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

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

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

后来的Pos​​tgreSQL版本默认为' 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中表示的字符等,然后你应该返回hex或base64表示并在客户端应用程序中解码它。