2011-01-26 3 views
4

私は現在、PL/Pythonでいくつかのデータの変換を実行するプロシージャを作成しようとしていますが、結果をbyteaとして返します。 (それは実際には、非常に醜いです:!?OCamlの中のデータをマーシャリングしPythonとOCamlので醜い一度、私が金メダルを取得する必要があります):それは書き込み、PL/Python PostgreSQLルーチンでバイナリ文字列(bytea)を返すにはどうすればよいですか?

要するに
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 

を各4つのバイトは、(〜130があるはずです)があります。ファイルのリンクを解除すると、その理由がわかります。 4つの非NULバイトが続き、その後に2つのNULが続き、それらのNULはPythonからPostgresへの変換によってある段階でターミネータとして扱われるようです!

なぜこのようなことが起こるのか、どのように停止するのかを知っていますか?ドキュメントは啓発されていません。

ありがとうございます!

someone else with the same problemが見つかりましたが、解決策はかなり不満足です。

答えて

4

リリース9.0で修正されました。私は同じ問題を抱えていたのでアップグレードしました。 release notesから:

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のバージョンでは、この問題のために非常にエレガントな解決策があるとは思いません。

+0

あまりにも簡単です。 ;-)ポインタありがとう! – Ashe

1

pythonの戻り値をbase64として別のbodge-encodeを適用し、PostgreSQLのデコード関数を使用してデコードすることができます。 decode(ml_marshal(xxx), 'base64')

アドリアンによると、9.0にアップグレードします。

+0

悪くない!しかし、それにもかかわらず含まれています。 – Ashe

関連する問題