Как вернуть двоичную строку (bytea) в процедуру PL / Python PostgreSQL? - PullRequest
4 голосов
/ 26 января 2011

В настоящее время я пытаюсь написать процедуру на 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 голосов
/ 26 января 2011

Это было исправлено в выпуске 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 есть очень элегантное решение этой проблемы.

1 голос
/ 26 января 2011

Вы можете применить другое bodge-кодирование возвращаемого значения из python как base64 и использовать функцию декодирования PostgreSQL для его декодирования, а именноdecode(ml_marshal(xxx), 'base64').

Или обновить до 9.0, как указано Адрианом:)

...