plpgsql 测试用例中的 SELECT 查询未返回数组

Posted

技术标签:

【中文标题】plpgsql 测试用例中的 SELECT 查询未返回数组【英文标题】:Array not being returned by SELECT query inside plpgsql test case 【发布时间】:2015-12-10 06:04:48 【问题描述】:

我正在使用的 SELECT 查询:

SELECT ARRAY[table_name,pg_size_pretty(table_size)]
FROM (
    SELECT
        table_name,
        pg_table_size(table_name) AS table_size,
        pg_indexes_size(table_name) AS indexes_size,
        pg_total_relation_size(table_name) AS total_size
    FROM (
        SELECT ('"' || table_schema || '"."' || table_name || '"') AS table_name
        FROM information_schema.tables where table_schema not in ('pg_catalog', 'information_schema')and table_schema not like 'pg_toast%'
    ) AS all_tables
    ORDER BY total_size DESC
) AS have ;

这会将输出返回为:

但是当我在 plpgsql 测试用例中使用相同的查询时,它不会返回相同的数组。

测试用例代码:

DROP FUNCTION IF EXISTS unit_tests.example2();

CREATE FUNCTION unit_tests.example2()
RETURNS test_result
AS
$$
DECLARE message test_result;
DECLARE result boolean;
DECLARE have text[][];
DECLARE want text[][];
BEGIN
    want := array[['"unit_tests"."tests"','8192 bytes'],
['"unit_tests"."test_details"','16 KB'],
['"unit_tests"."dependencies"','8192 bytes'],
['"DVDRental"."dvd_genre"','8192 bytes'],
['"DVDRental"."dvd_stock"','0 bytes']];

SELECT ARRAY[table_name,pg_size_pretty(table_size)] INTO have
FROM (
    SELECT
        table_name,
        pg_table_size(table_name) AS table_size,
        pg_indexes_size(table_name) AS indexes_size,
        pg_total_relation_size(table_name) AS total_size
    FROM (
        SELECT ('"' || table_schema || '"."' || table_name || '"') AS table_name
        FROM information_schema.tables where table_schema not in ('pg_catalog', 'information_schema')and table_schema not like 'pg_toast%'
    ) AS all_tables
    ORDER BY total_size DESC
) AS have ;

    SELECT * FROM assert.is_equal(have, want) INTO message, result;

    --Test failed.
    IF result = false THEN
        RETURN message;
    END IF;

    --Test passed.
    SELECT assert.ok('End of test.') INTO message;  
    RETURN message; 
END
$$
LANGUAGE plpgsql;

--BEGIN TRANSACTION;
SELECT * FROM unit_tests.begin();
--ROLLBACK TRANSACTION;

代码返回的结果:

INFO:  Test started from : 2015-12-10 05:50:37.291
INFO:  Running test unit_tests.example2() : 2015-12-10 05:50:37.291
INFO:  Test failed unit_tests.example2() : ASSERT IS_EQUAL FAILED.

Have -> "\"unit_tests\".\"tests\"","8192 bytes"
Want -> "\"unit_tests\".\"tests\"","8192 bytes","\"unit_tests\".\"test_details\"","16 KB","\"unit_tests\".\"dependencies\"","8192 bytes","\"DVDRental\".\"dvd_genre\"","8192 bytes","\"DVDRental\".\"dvd_stock\"","0 bytes"
INFO:  Test completed on : 2015-12-10 05:50:37.322 UTC. 

这里have 变量代表查询返回的结果,want 变量具有我们期望查询返回的值。但正如我们所见,have 中的值并不是查询最初返回的值。

这是我使用 INTO 关键字或其他与函数相关的方式的问题吗?

更新看起来只有结果集的第一个值被分配给 have 变量,也许如果我们可以迭代返回的结果然后将其分配给 have,这可能会起作用。

【问题讨论】:

【参考方案1】:

您不是第一个遇到这种情况的人。目前,array_agg()(或数组构造函数ARRAY(SELECT ...) 只接受标量值作为输入,而不接受数组类型。所以你不能用它构建多维数组。

不过,修复很简单。创建自定义聚合函数:

CREATE AGGREGATE array_agg_mult (anyarray)  (
    SFUNC     = array_cat
   ,STYPE     = anyarray
   ,INITCOND  = ''
);

在简化了一些其他事情之后,您的函数的基本版本变为:

CREATE FUNCTION example2()
  RETURNS text[] AS
$func$
SELECT array_agg_mult(ARRAY[ARRAY[tbl, pg_size_pretty(pg_table_size(tbl))]]
                      ORDER BY pg_total_relation_size(tbl) DESC) AS have
FROM (
   SELECT format('%I.%I', table_schema, table_name) AS tbl
   FROM   information_schema.tables
   WHERE  table_schema NOT LIKE 'pg_%'
   AND    table_schema <> 'information_schema'
   ) AS all_tables
$func$  LANGUAGE sql;

相关(展望 Postgres 9.5):

Selecting data into a Postgres array

【讨论】:

以上是关于plpgsql 测试用例中的 SELECT 查询未返回数组的主要内容,如果未能解决你的问题,请参考以下文章

测试用例中的细节

如何模拟酶测试用例中的拖放?

测试用例中的分段错误

使用 Java 反射访问测试用例中的受保护方法

Google Kickstart 2018,测试用例中的回合错误

在代码中的 Chech 括号中的测试用例中得到错误的输出