PL / Python3 - объединение PLyResults - PullRequest
0 голосов
/ 26 июня 2019

Мне интересно, возможно ли каким-либо образом объединить PLyResults внутри функции. Например, допустим, во-первых, у меня есть функция _get_data, которая при наличии кортежа (id, index) возвращает таблицу значений:

CREATE OR REPLACE FUNCTION _get_data(id bigint, index bigint):
RETURNS TABLE(oid bigint, id bigint, val double precision) AS
$BODY$

#...process for fetching the data, irrelevant for the question.
return recs    

$BODY$
LANGUAGE plpython3u;

Теперь я хотел бы иметь возможность создать универсальную функцию, определенную как таковую, которая выбирает данные между двумя границами для данного идентификатора и использует предыдущую функцию для выборки данных по отдельности, а затем как-то агрегирует результаты:

CREATE OR REPLACE FUNCTION get_data(id bigint, lbound bigint, ubound bigint)
RETURNS TABLE(oid bigint, id bigint, val double precision) AS
$BODY$

concatenated_recs = [] #<-- For the sake of argument.
plan = plpy.prepare("SELECT oid, id, val FROM _get_data($1, $2);", ['bigint', 'bigint'])
for i in range(lbound, ubound+1):
    recs = plpy.execute(plan, [id, i]) # <-- Records fetched individually 
    concatenated_recs += [recs] #<-- Not sure how to concatenate them...

return concatenated_recs

$BODY$
LANGUAGE plpython3u; 

Ответы [ 2 ]

0 голосов
/ 26 июня 2019

Возможно, я что-то упускаю, но ответ, который вы дали, выглядит как более медленная и более сложная версия этого запроса:

SELECT oid, id, val 
FROM generate_series(your_lower_bound, your_upper_bound) AS g(i),
_get_data(your_id, i);

Вы можете поместить это в простую функцию SQL без циклов или временных таблиц:

CREATE OR REPLACE FUNCTION get_data(id bigint, lbound bigint, ubound bigint)
RETURNS TABLE(oid bigint, id bigint, val double precision) AS
$BODY$
SELECT oid, id, val 
FROM generate_series(lbound, ubound) AS g(i),
_get_data(id, i);
$BODY$ LANGUAGE SQL;
0 голосов
/ 26 июня 2019

Хотя я не смог найти способ объединить результаты из документации PL / Python, и по состоянию на 06-2019 я не уверен, что язык поддерживает этот ресурс, но я мог бы решить его, создаввременная таблица, вставляя в нее записи для каждой итерации и затем возвращая полную таблицу:

CREATE OR REPLACE FUNCTION get_data(id bigint, lbound bigint, ubound bigint)
RETURNS TABLE(oid bigint, id bigint, val double precision) AS
$BODY$

#Creates the temp table
plpy.execute("""CREATE TEMP TABLE temp_results(oid bigint, id bigint, val double precision)
ON COMMIT DROP""")

plan = plpy.prepare("INSERT INTO temp_results SELECT oid, id, val FROM _get_data($1, $2);", 
['bigint', 'bigint'])

#Inserts the results in the temp table
for i in range(lbound, ubound+1):
    plpy.execute(plan, [id, i])

#Returns the whole table
recs = plpy.execute("SELECT * FROM temp_results")
return recs

$BODY$
LANGUAGE plpython3u; 
...