Я использую Postgresql 9.4, и я не понимаю, как он обрабатывает импорт plpython, особенно в отношении Decimal.
Первый пример:
CREATE OR REPLACE FUNCTION devel.foo()
RETURNS void AS
$BODY$
def myfoo():
eval("Decimal('40.0')")
myfoo()
plpy.notice("done")
$BODY$
LANGUAGE plpythonu VOLATILE
COST 100;
ALTER FUNCTION devel.foo()
OWNER TO postgres;
SELECT devel.foo();
Результат:
ОШИБКА: NameError: имя «Десятичное число» не определено
Немного удивительно, поскольку одно из изменений в Postgresql 9.4 заключается в том, что предполагается неявное использование Decimal вместо float внутри plpython. Но хорошо, давайте добавим импорт:
CREATE OR REPLACE FUNCTION devel.foo()
RETURNS void AS
$BODY$
from decimal import Decimal
def myfoo():
eval("Decimal('40.0')");
myfoo()
plpy.notice("done")
$BODY$
LANGUAGE plpythonu VOLATILE
COST 100;
ALTER FUNCTION devel.foo()
OWNER TO postgres;
select devel.foo()
Опять таки:
ОШИБКА: NameError: имя «Десятичное число» не определено
Теперь попробуем разместить импорт внутри функции:
CREATE OR REPLACE FUNCTION devel.foo()
RETURNS void AS
$BODY$
def myfoo():
from decimal import Decimal
eval("Decimal('40.0')")
myfoo()
plpy.notice("done")
$BODY$
LANGUAGE plpythonu VOLATILE
COST 100;
ALTER FUNCTION devel.foo()
OWNER TO postgres;
select devel.foo();
Результат: devel.foo()
теперь выполняется без проблем, печатая 'done'. Еще одна любопытная вещь: также работает следующее:
CREATE OR REPLACE FUNCTION devel.foo()
RETURNS void AS
$BODY$
from decimal import Decimal
def myfoo():
var = Decimal('40.0')
eval("Decimal('40.0')")
myfoo()
plpy.notice("done")
$BODY$
LANGUAGE plpythonu VOLATILE
COST 100;
ALTER FUNCTION devel.foo()
OWNER TO postgres;
Вопросы: почему импорт верхнего уровня не виден внутри myfoo()
? Почему это вдруг работает, если я использую Decimal внутри функции?