Teach PL/pgSQL about partitioned tables.

Table partitioning, introduced in commit f0e44751d7, added a new
relkind - RELKIND_PARTITIONED_TABLE. Update a couple of places in
PL/pgSQL to handle it. Specifically plpgsql_parse_cwordtype() and
build_row_from_class() needed updating in order to make table%ROWTYPE
and table.col%TYPE work for partitioned tables.

Dean Rasheed, reviewed by Amit Langote.

Discussion: https://postgr.es/m/CAEZATCUnNOKN8sLML9jUzxecALWpEXK3a3W7y0PgFR4%2Buhgc%3Dg%40mail.gmail.com
This commit is contained in:
Dean Rasheed 2017-06-14 09:00:01 +01:00
parent f356ec5744
commit d3c3f2b1e2
3 changed files with 88 additions and 2 deletions

View File

@ -1761,7 +1761,8 @@ plpgsql_parse_cwordtype(List *idents)
classStruct->relkind != RELKIND_VIEW &&
classStruct->relkind != RELKIND_MATVIEW &&
classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
classStruct->relkind != RELKIND_FOREIGN_TABLE)
classStruct->relkind != RELKIND_FOREIGN_TABLE &&
classStruct->relkind != RELKIND_PARTITIONED_TABLE)
goto done;
/*
@ -1987,7 +1988,8 @@ build_row_from_class(Oid classOid)
classStruct->relkind != RELKIND_VIEW &&
classStruct->relkind != RELKIND_MATVIEW &&
classStruct->relkind != RELKIND_COMPOSITE_TYPE &&
classStruct->relkind != RELKIND_FOREIGN_TABLE)
classStruct->relkind != RELKIND_FOREIGN_TABLE &&
classStruct->relkind != RELKIND_PARTITIONED_TABLE)
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("relation \"%s\" is not a table", relname)));

View File

@ -5979,3 +5979,48 @@ LINE 1: SELECT (SELECT string_agg(id || '=' || name, ',') FROM d)
^
QUERY: SELECT (SELECT string_agg(id || '=' || name, ',') FROM d)
CONTEXT: PL/pgSQL function alter_table_under_transition_tables_upd_func() line 3 at RAISE
--
-- Check type parsing and record fetching from partitioned tables
--
CREATE TABLE partitioned_table (a int, b text) PARTITION BY LIST (a);
CREATE TABLE pt_part1 PARTITION OF partitioned_table FOR VALUES IN (1);
CREATE TABLE pt_part2 PARTITION OF partitioned_table FOR VALUES IN (2);
INSERT INTO partitioned_table VALUES (1, 'Row 1');
INSERT INTO partitioned_table VALUES (2, 'Row 2');
CREATE OR REPLACE FUNCTION get_from_partitioned_table(partitioned_table.a%type)
RETURNS partitioned_table AS $$
DECLARE
a_val partitioned_table.a%TYPE;
result partitioned_table%ROWTYPE;
BEGIN
a_val := $1;
SELECT * INTO result FROM partitioned_table WHERE a = a_val;
RETURN result;
END; $$ LANGUAGE plpgsql;
NOTICE: type reference partitioned_table.a%TYPE converted to integer
SELECT * FROM get_from_partitioned_table(1) AS t;
a | b
---+-------
1 | Row 1
(1 row)
CREATE OR REPLACE FUNCTION list_partitioned_table()
RETURNS SETOF partitioned_table.a%TYPE AS $$
DECLARE
row partitioned_table%ROWTYPE;
a_val partitioned_table.a%TYPE;
BEGIN
FOR row IN SELECT * FROM partitioned_table ORDER BY a LOOP
a_val := row.a;
RETURN NEXT a_val;
END LOOP;
RETURN;
END; $$ LANGUAGE plpgsql;
NOTICE: type reference partitioned_table.a%TYPE converted to integer
SELECT * FROM list_partitioned_table() AS t;
t
---
1
2
(2 rows)

View File

@ -4766,3 +4766,42 @@ ALTER TABLE alter_table_under_transition_tables
DROP column name;
UPDATE alter_table_under_transition_tables
SET id = id;
--
-- Check type parsing and record fetching from partitioned tables
--
CREATE TABLE partitioned_table (a int, b text) PARTITION BY LIST (a);
CREATE TABLE pt_part1 PARTITION OF partitioned_table FOR VALUES IN (1);
CREATE TABLE pt_part2 PARTITION OF partitioned_table FOR VALUES IN (2);
INSERT INTO partitioned_table VALUES (1, 'Row 1');
INSERT INTO partitioned_table VALUES (2, 'Row 2');
CREATE OR REPLACE FUNCTION get_from_partitioned_table(partitioned_table.a%type)
RETURNS partitioned_table AS $$
DECLARE
a_val partitioned_table.a%TYPE;
result partitioned_table%ROWTYPE;
BEGIN
a_val := $1;
SELECT * INTO result FROM partitioned_table WHERE a = a_val;
RETURN result;
END; $$ LANGUAGE plpgsql;
SELECT * FROM get_from_partitioned_table(1) AS t;
CREATE OR REPLACE FUNCTION list_partitioned_table()
RETURNS SETOF partitioned_table.a%TYPE AS $$
DECLARE
row partitioned_table%ROWTYPE;
a_val partitioned_table.a%TYPE;
BEGIN
FOR row IN SELECT * FROM partitioned_table ORDER BY a LOOP
a_val := row.a;
RETURN NEXT a_val;
END LOOP;
RETURN;
END; $$ LANGUAGE plpgsql;
SELECT * FROM list_partitioned_table() AS t;