如何在PL/Python PostgreSQL例程中返回二进制字符串(bytea)?

4
我目前正在尝试编写一个PL/Python过程来执行一些数据转换,然后将结果作为bytea返回。(实际上很丑:在OCaml中编组数据! Python和OCaml同时很丑陋;我应该获得奖章吗?)
这是它的样子:
CREATE OR REPLACE FUNCTION ml_marshal(data varchar) RETURNS bytea as $$
    import tempfile, os

    fn = tempfile.mktemp()
    f = open(fn, 'w')

    dest_fn = tempfile.mktemp()

    f.write("let outch = open_out_bin \"" + dest_fn + "\" in " +
            "Marshal.to_channel outch (" + data + ") [Marshal.No_sharing]; " +
            "close_out outch")
    f.close()

    os.system("ocaml " + fn)
    os.unlink(fn)

    f = open(dest_fn, 'r')
    res = f.read()
    f.close()

    os.unlink(dest_fn)

    return res
$$ LANGUAGE plpythonu;

简而言之,它将一个小的OCaml程序写入一个临时文件中,该程序创建另一个包含我们想要数据的临时文件。然后我们读取该临时文件,销毁两个文件,并返回结果。
只是它并没有完全起作用:
meidi=# select * from tblmodel;
 modelid |      polies      
---------+------------------
       1 | \204\225\246\276
       2 | \204\225\246\276

每个中有四个字节(应该有大约130个)。如果我停止解除文件的链接,就会变得很明显;有四个非NUL字节,然后是几个NUL,似乎这些NUL在某个阶段被转换从Python到Postgres时被视为终止符!
有人知道为什么会发生这种情况,或者如何停止它吗?文档没有提供启示。
谢谢!
编辑:我找到了有相同问题的其他人,但解决方案相当不令人满意。
2个回答

4

这个问题在9.0版本中得到了修复。我之前也遇到过同样的问题,所以我进行了升级。根据发布说明

Improve bytea support in PL/Python (Caleb Welton)

Bytea values passed into PL/Python are now represented as binary, rather than the PostgreSQL bytea text format. Bytea values containing null bytes are now also output properly from PL/Python. Passing of boolean, integer, and float values was also improved.

我认为在以前的PostgreSQL版本中,对于这个问题没有非常优雅的解决方案。


2
你可以采用另一种方法——将Python的返回值编码为base64,并使用PostgreSQL的decode函数进行解码,如下所示:decode(ml_marshal(xxx), 'base64')
或者按照Adrian的建议升级到9.0版本 :)

不错!确实是一个临时应急方案,但仍然是一个局部的解决办法。 - Asherah

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接