Array not being returned by SELECT query inside plpgsql test case

一笑奈何 提交于 2020-01-16 05:03:08

问题


SELECT query I am using:

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 ;

This returns the output as:

But when I use the same query inside a plpgsql test case, it doesn't return me the same array.

Code for the test case:

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;

Result being returned by the code:

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. 

Here have variable represents the result of the query being returned and want variable has the value which we expected the query to return. But as we can see the value in haveis not what the query was originally returning.

Is this an issue with the way I am using INTO keyword or something else related to functions?

UPDATE Looks like only the first value of the resultset is being assigned to the have variable, maybe if we can iterate of the results returned and then assign it to have, that might work.


回答1:


You are not the first to run into this. Currently, array_agg() (or the array constructor ARRAY(SELECT ...) only accept scalar values as input, not array types. so you cannot build multi-dimensional arrays with it.

The fix is simple, though. Create a custom aggregate function:

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

After simplifying a couple of other things, a basic version of your function becomes:

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;

Related (with an outlook to Postgres 9.5):

  • Selecting data into a Postgres array


来源:https://stackoverflow.com/questions/34194818/array-not-being-returned-by-select-query-inside-plpgsql-test-case

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!