2015-12-02 51 views
0

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

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的人可以指出我正确的方向来解决这个问题。

+0

什么是“正确”?显示你认为它*应该*也是。猜测你遇到了默认的'bytea_output'设置更改的问题。 –

+0

在这种情况下,正确的响应应该是“管理员”。 – kdavej

+0

Npgsql 2.0.12绝对是古老的...你绝对应该尝试升级到最新的3.x –

回答

1

你一直依靠在当前编码中将bytea输出解释为一个字符串,也就是说,你的代码一直是错误的,但碰巧有效。

较旧的PostgreSQL版本对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版本默认为“十六进制”输出,编码一切为十六进制:

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等中表示的字符,那么您应该返回十六进制或base64表示并在客户端应用程序中对其进行解码。

+0

谢谢!这是遗留系统,更新应用程序中的每个查询都不会是一个好场景。我能够将服务器配置为恢复旧的“转义”格式,以便在我们制定更好的整体解决方案时保持我们的状态。 – kdavej