0

我正在替换get_data我们数据库中的一个遗留函数,它需要一些entity_id并返回一个引用。

我正在编写一个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

4

1 回答 1

0

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

在这种特定情况下,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'
);
于 2022-01-26T21:57:44.123 回答