Тестирование функций PostgreSQL, которые потребляют и возвращают refcursor
Я хочу проверить результаты функции Postgres (изменение функции не является возможным).
функция получает в качестве аргументов РЕФКУРСОР и несколько других вещей и возвращает тот же РЕКУРСОР.
get_function_that_returns_cursor(ret, 4100, 'SOMETHING', 123465)
теперь я хочу создать небольшой тест в Postgres, чтобы получить результаты этой функции. Что-то вроде кода ниже (это мой подход, но он не работает):
DO $$ DECLARE
ret REFCURSOR;
row_to_read table_it_will_return%ROWTYPE ;
BEGIN
PERFORM get_function_that_returns_cursor(ret, 4100, 'SOMETHING', 123465);
-- OR SELECT get_function_that_returns_cursor(ret, 4100, 'SOMETHING', 123465) INTO ret
FOR row_to_read IN SELECT * FROM ret LOOP
-- (...)
RAISE NOTICE 'Row read...';
END LOOP;
CLOSE ret;
END $$;
любое предложение о том, как заставить это работать? Общее решение что можно использовать для тестирования этого типа функций (которые получают курсор и возвращают курсор?
и если мы не знаем тип строки, который возвращается, как мы могли бы это сделать?
каков наилучший способ отладки такого рода вещей в PostgresQL
2 ответов
1 квартале
ваш "маленький тест" может быть простым SQL:
BEGIN;
SELECT get_function_that_returns_cursor('ret', 4100, 'foo', 123); -- note: 'ret'
FETCH ALL IN ret; -- works for any rowtype
COMMIT; -- or ROLLBACK;
выполнить COMMIT
/ ROLLBACK
после вы проверили результаты. Большинство клиентов отображают только результат команды lat.
в главе Возвращаясь Курсоры руководства.
Q2
и если мы не знаем тип строки, который возвращается, как мы могли бы это сделать?
так как вы только хотите проверить результаты, вы могли бы бросьте всю запись в text
.
Таким образом, вы избегаете проблемы с динамическими типами возврата для функции в целом.
рассмотрим эту демонстрацию:
CREATE TABLE a (a_id int PRIMARY KEY, a text);
INSERT INTO a VALUES (1, 'foo'), (2, 'bar');
CREATE OR REPLACE FUNCTION reffunc(INOUT ret refcursor) AS -- INOUT param :)
$func$
BEGIN
OPEN ret FOR SELECT * FROM a;
END
$func$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION ctest()
RETURNS SETOF text AS
$func$
DECLARE
curs1 refcursor;
rec record;
BEGIN
curs1 := reffunc('ret'); -- simple assignment
LOOP
FETCH curs1 INTO rec;
EXIT WHEN NOT FOUND; -- note the placement!
RETURN NEXT rec::text;
END LOOP;
END
$func$ LANGUAGE plpgsql;
это сработало для того, что я хотел:
DO $$ DECLARE
mycursor REFCURSOR;
rec RECORD;
BEGIN
SELECT 'ret' INTO mycursor FROM get_function_that_returns_cursor('ret'::REFCURSOR, 4100, 'SOMETHING', 123465);
WHILE (FOUND) LOOP
FETCH mycursor INTO rec;
RAISE NOTICE 'Row read. Data: % ', rec.collumn_name;
END LOOP;
END $$