Входные параметры таблицы и скалярные выходные параметры - PullRequest
0 голосов
/ 03 января 2019

У меня есть следующая таблица и следующая хранимая процедура (упрощенная до простых основ, необходимых для демонстрации проблемы):

CREATE TABLE T(C INT);
CREATE PROCEDURE PROC(IN T TABLE(C INT), OUT X INT) AS BEGIN
X = 5;
END;

Из HANA Studio я могу CALL PROC(T, ?) и получить 5. ОднакоЯ не нашел ни одного хорошего способа сделать то же самое с драйвером Python hdbcli .

callproc, похоже, не может принять параметры таблицы.Передача имени таблицы в виде строки не работает:

>>> from hdbcli import dbapi
>>> conn = dbapi.connect(userkey='testkey')
>>> cur = conn.cursor()
>>> cur.callproc('PROC', ('T', '?'))
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/hdbcli/dbapi.py", line 498, in callproc
    ret = self.__callproc(callproc, parameters)
  File "/usr/local/lib/python3.6/site-packages/hdbcli/dbapi.py", line 257, in __callproc
    return self.__cursor.callproc(operation, parameters)
hdbcli.dbapi.Error: (8, 'invalid argument: Input parameter is inadequate as table parameter: line 1 col 13 (at pos 12)')

execute может выполнить процедуру, но, по-видимому, она не предоставляет никакого способа доступа к выходному параметру.Для него нет набора результатов:

>>> cur.execute('CALL PROC(T, ?)')
True
>>> cur.fetchone()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python3.6/site-packages/hdbcli/dbapi.py", line 434, in fetchone
    raise ProgrammingError(0,"No result set")
hdbcli.dbapi.ProgrammingError: (0, 'No result set')

Я нашел один чрезвычайно неуклюжий обходной путь, который я публикую в качестве ответа, но он ужасно многословен и плохо взаимодействует со значениями параметров по умолчанию.Есть ли хороший способ получить доступ к выходному параметру?

1 Ответ

0 голосов
/ 03 января 2019

Единственный обходной путь, который я нашел, - это обернуть процедуру в анонимный блок и вставить скаляр в SELECT в анонимном блоке:

>>> cur.execute('''
... DO BEGIN
... DECLARE X INT;
... T_VAR = SELECT * FROM T;
... CALL PROC(:T_VAR, X);
... SELECT :X FROM DUMMY;
... END''')
True
>>> cur.fetchone()
(5,)

Это много лишней типизации.Мы можем сохранить процедуру-обертку, чтобы сделать это для нас, вместо того, чтобы каждый раз повторять анонимный блок, но это может привести к множеству процедур-оберток, если у вас есть много процедур для обертывания.Кроме того, он не очень хорошо работает со значениями по умолчанию.Если у вас есть следующая процедура:

CREATE PROCEDURE PROC2(OUT X INT, IN T TABLE(C INT) DEFAULT T) AS BEGIN
X = 5;
END;

Обычно вы можете вызвать ее как CALL PROC2(?), но вы не можете вызвать ее из анонимного блока или хранимой процедуры, не передав явное значение для T:

>>> cur.execute('''
... DO BEGIN
... DECLARE X INT;
... CALL PROC2(X);
... SELECT :X FROM DUMMY;
... END''')
Traceback (most recent call last):
  File "<stdin>", line 6, in <module>
  File "/usr/local/lib/python3.6/site-packages/hdbcli/dbapi.py", line 363, in execute
    ret = self.__execute(operation)
  File "/usr/local/lib/python3.6/site-packages/hdbcli/dbapi.py", line 249, in __execute
    ret = self.__cursor.execute(operation, parameters=parameters, iscall=iscall, scrollable=self._scrollable)
hdbcli.dbapi.Error: (7, 'feature not supported: Only table variable is allowed in input parameter in a nested call: line 1 col 15 (at pos 14)')

Это исключение происходит из-за значения по умолчанию T.

...