Postgresql: проблема с выбором массивов в функции, возвращающей множество plpgsql - PullRequest
2 голосов
/ 02 августа 2011

Я пытаюсь выбрать массивы в функции, возвращающей множество в postgres 8.4, но получаю ошибка:

"значение массива должно начинаться с" {"или информации о размерах" .

Эта проблема иногда связана с locationnodes.rs_people_c. имея пустой массив. Я пытался обойти это с заявлением COALESCE. Не повезло.

функция

CREATE OR REPLACE FUNCTION fn_matview_location_slots (
    week_start  DATE
) RETURNS setof matview_location_slots_info AS
$$
DECLARE
    resulter    matview_location_slots_info%ROWTYPE;
BEGIN
    FOR resulter IN
        SELECT
            rs_node               AS node,
            rs_date               AS dater,
            ...
            COALESCE(rs_people_c, '{}'::INTEGER[]) AS people,
            rs_location           AS location
        FROM
            locationnodes
        WHERE
            rs_date >= week_start
    LOOP
        RETURN NEXT resulter;
    END LOOP;
END; $$ LANGUAGE plpgsql;

Тип

CREATE TYPE matview_location_slots_info AS (
        node              VARCHAR,
        dater             DATE,
        ...
        people            INTEGER[],
        location          INTEGER[]
);

Данные

select rs_people_c from locationnodes;
           rs_people_c
-------------------------------------
 {}
 {}
 {731}
 {32}
 {31}
 {}
 {62}
 {540,72,69,53,37,42,201,51,58}
 {64}

Ответы [ 2 ]

1 голос
/ 03 августа 2011

В дополнение к ответу @ rorycl, здесь есть рабочий тестовый сценарий под PostgreSQL 8.4.8:

DROP TYPE IF EXISTS matview_location_slots_info;
CREATE TYPE matview_location_slots_info AS
(
    node varchar,
    dater date,
    people integer[]
);
DROP TABLE IF EXISTS locationnodes;
CREATE TABLE locationnodes
(
    rs_node varchar,
    rs_date date,
    rs_people_c integer[]
);
INSERT INTO locationnodes VALUES
    ('aaa', '2011-01-01', '{}'),
    ('bbb', '2011-01-02', '{}'),
    ('ccc', '2011-01-03', '{731}'),
    ('ddd', '2011-01-04', '{32}'),
    ('eee', '2011-01-05', '{31}'),
    ('fff', '2011-01-06', '{}'),
    ('ggg', '2011-01-07', '{62}'),
    ('hhh', '2011-01-08', '{540, 72, 69, 53, 37, 42, 201, 51, 58}'),
    ('iii', '2011-01-09', '{64}');

Функция PL / pgSQL:

CREATE OR REPLACE FUNCTION fn_matview_location_slots (week_start date)
RETURNS setof matview_location_slots_info AS $$
DECLARE
    resulter matview_location_slots_info%ROWTYPE;
BEGIN
    FOR resulter IN
        SELECT
            rs_node AS node,
            rs_date AS dater,
            rs_people_c AS people
        FROM
            locationnodes
        WHERE
            rs_date >= week_start
    LOOP
        RETURN NEXT resulter;
    END LOOP;
END; $$ LANGUAGE plpgsql;

Результат:

SELECT fn_matview_location_slots('2011-01-01');
             fn_matview_location_slots
---------------------------------------------------
 (aaa,2011-01-01,{})
 (bbb,2011-01-02,{})
 (ccc,2011-01-03,{731})
 (ddd,2011-01-04,{32})
 (eee,2011-01-05,{31})
 (fff,2011-01-06,{})
 (ggg,2011-01-07,{62})
 (hhh,2011-01-08,"{540,72,69,53,37,42,201,51,58}")
 (iii,2011-01-09,{64})
(9 rows)
1 голос
/ 03 августа 2011

Я допустил глупую ошибку определения типа (которую я исключил из своего первоначального вопроса, но Гжегож упомянул - спасибо Гжегожу).

Я публикую это как ответ для любого, кто ищет проблему с значение массива должно начинаться с "{" или информации о размере .

В моем случае проблема заключалась в том, что тип возвращаемого значения местоположения был определен как массив целых чисел, но функция возвращала простое целое число.К сожалению, Postgres не предоставляет больше информации о конкретной проблеме в этих случаях.

Также обратите внимание, что в этом случае вам не нужно объединять NULL-массивы в {}, как я делал в своем вопросе.

Вкратце: убедитесь, что возвращаемые вами массивы получают входные данные массива!

...