Postgres:如何在比较之前转换两个游标中的数据



我正在替换数据库中的一个遗留函数get_data,它接受一些entity_id并返回一个refcursor。

我正在编写一个新函数get_data_new,它使用不同的数据源,但对于相同的输入,输出应该与get_data相同。

我想用pgtap验证这一点,并在测试中按照如下方式进行验证(_expected_actual是返回游标的名称(:

SELECT schema.get_data('_expected', 123);
SELECT schema.get_data_new('_actual', 123);
SELECT results_eq(
'FETCH ALL FROM _actual',
'FETCH ALL FROM _expected',
'get_data_new should return identical results to the legacy version'
);

这与其他函数的预期一样,但get_data中的查询恰好返回了一些json列,这意味着与ERROR: could not identify an equality operator for type json的比较预计会失败。

我宁愿保留遗留函数,这样就不可能重构到jsonb。我设想了一种变通方法,即在比较之前转换数据,假设使用SELECT entity_id, json_column::jsonb FROM (FETCH ALL FROM _actual)之类的方法,但这种特定的尝试显然是无效的。

这里建议的方法是什么?编写一个助手函数,将游标中的数据插入到几个临时表中?我希望有一个我还没有发现的更清洁的解决方案。

使用postgres 11.14,pgtap11

通过创建一个函数在光标上循环并将结果作为表返回,解决了这个问题。不幸的是,这不是一个通用的解决方案——它只适用于具有特定数据的游标。

在这种特定情况下,json_column可以隐式转换为类型jsonb,因此这就是所需的全部内容。然而,我们现在可以SELECT * FROM cursor_to_table('_actual'),这意味着我们可以对结果进行任何需要的转换。

CREATE OR REPLACE FUNCTION cursor_to_table(_cursor refcursor)
RETURNS TABLE (entity_id bigint, json_column jsonb)
AS $func$
BEGIN
LOOP
FETCH _cursor INTO entity_id, json_column
EXIT WHEN NOT FOUND;
RETURN NEXT;
END LOOP;
RETURN;
END
$func$  LANGUAGE plpgsql;
SELECT results_eq(
'SELECT * FROM cursor_to_table(''_actual'')',
'SELECT * FROM cursor_to_table(''_expected'')',
'get_data_new should return identical results to the legacy version'
);

最新更新