-- keep these tests aligned with generated_virtual.sql
CREATESCHEMA generated_stored_tests; GRANTUSAGEONSCHEMA generated_stored_tests TO PUBLIC; SET search_path = generated_stored_tests;
CREATETABLE gtest0 (a intPRIMARYKEY, b int GENERATED ALWAYS AS (55) STORED); CREATETABLE gtest1 (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a * 2) STORED);
SELECT table_name, column_name, column_default, is_nullable, is_generated, generation_expression FROM information_schema.columns WHERE table_schema = 'generated_stored_tests'ORDERBY1, 2;
SELECT table_name, column_name, dependent_column FROM information_schema.column_column_usage WHERE table_schema = 'generated_stored_tests'ORDERBY1, 2, 3;
\d gtest1
-- duplicate generated CREATETABLE gtest_err_1 (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a * 2) STORED GENERATED ALWAYS AS (a * 3) STORED);
-- references to other generated columns, including self-references CREATETABLE gtest_err_2a (a intPRIMARYKEY, b int GENERATED ALWAYS AS (b * 2) STORED); CREATETABLE gtest_err_2b (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a * 2) STORED, c int GENERATED ALWAYS AS (b * 3) STORED); -- a whole-row var is a self-reference on steroids, so disallow that too CREATETABLE gtest_err_2c (a intPRIMARYKEY,
b int GENERATED ALWAYS AS (num_nulls(gtest_err_2c)) STORED);
-- invalid reference CREATETABLE gtest_err_3 (a intPRIMARYKEY, b int GENERATED ALWAYS AS (c * 2) STORED);
-- generation expression must be immutable CREATETABLE gtest_err_4 (a intPRIMARYKEY, b doubleprecision GENERATED ALWAYS AS (random()) STORED); -- ... but be sure that the immutability test is accurate CREATETABLE gtest2 (a int, b text GENERATED ALWAYS AS (a || ' sec') STORED); DROPTABLE gtest2;
-- cannot have default/identity and generated CREATETABLE gtest_err_5a (a intPRIMARYKEY, b intDEFAULT5 GENERATED ALWAYS AS (a * 2) STORED); CREATETABLE gtest_err_5b (a intPRIMARYKEY, b int GENERATED ALWAYS AS identity GENERATED ALWAYS AS (a * 2) STORED);
-- reference to system column not allowed in generated column -- (except tableoid, which we test below) CREATETABLE gtest_err_6a (a intPRIMARYKEY, b bool GENERATED ALWAYS AS (xmin <> 37) STORED);
-- various prohibited constructs CREATETABLE gtest_err_7a (a intPRIMARYKEY, b int GENERATED ALWAYS AS (avg(a)) STORED); CREATETABLE gtest_err_7b (a intPRIMARYKEY, b int GENERATED ALWAYS AS (row_number() OVER (ORDERBY a)) STORED); CREATETABLE gtest_err_7c (a intPRIMARYKEY, b int GENERATED ALWAYS AS ((SELECT a)) STORED); CREATETABLE gtest_err_7d (a intPRIMARYKEY, b int GENERATED ALWAYS AS (generate_series(1, a)) STORED);
-- GENERATED BY DEFAULT not allowed CREATETABLE gtest_err_8 (a intPRIMARYKEY, b int GENERATED BYDEFAULTAS (a * 2) STORED);
SELECT * FROM gtest1 ORDERBY a; SELECT gtest1 FROM gtest1 ORDERBY a; -- whole-row reference SELECT a, (SELECT gtest1.b) FROM gtest1 ORDERBY a; -- sublink DELETEFROM gtest1 WHERE a >= 3;
UPDATE gtest1 SET b = DEFAULTWHERE a = 1; UPDATE gtest1 SET b = 11WHERE a = 1; -- error
SELECT * FROM gtest1 ORDERBY a;
SELECT a, b, b * 2AS b2 FROM gtest1 ORDERBY a; SELECT a, b FROM gtest1 WHERE b = 4ORDERBY a;
-- test that overflow error happens on write INSERTINTO gtest1 VALUES (2000000000); SELECT * FROM gtest1; DELETEFROM gtest1 WHERE a = 2000000000;
-- test with joins CREATETABLE gtestx (x int, y int); INSERTINTO gtestx VALUES (11, 1), (22, 2), (33, 3); SELECT * FROM gtestx, gtest1 WHERE gtestx.y = gtest1.a; DROPTABLE gtestx;
-- test UPDATE/DELETE quals SELECT * FROM gtest1 ORDERBY a; UPDATE gtest1 SET a = 3WHERE b = 4 RETURNING old.*, new.*; SELECT * FROM gtest1 ORDERBY a; DELETEFROM gtest1 WHERE b = 2; SELECT * FROM gtest1 ORDERBY a;
-- test MERGE CREATETABLE gtestm (
id intPRIMARYKEY,
f1 int,
f2 int,
f3 int GENERATED ALWAYS AS (f1 * 2) STORED,
f4 int GENERATED ALWAYS AS (f2 * 2) STORED
); INSERTINTO gtestm VALUES (1, 5, 100);
MERGE INTO gtestm t USING (VALUES (1, 10), (2, 20)) v(id, f1) ON t.id = v.id WHEN MATCHED THENUPDATESET f1 = v.f1 WHENNOT MATCHED THENINSERTVALUES (v.id, v.f1, 200)
RETURNING merge_action(), old.*, new.*; SELECT * FROM gtestm ORDERBY id; DROPTABLE gtestm;
CREATETABLE gtestm (
a intPRIMARYKEY,
b int GENERATED ALWAYS AS (a * 2) STORED
); INSERTINTO gtestm (a) SELECT g FROM generate_series(1, 10) g;
MERGE INTO gtestm t USING gtestm AS s ON2 * t.a = s.b WHEN MATCHED THENDELETE RETURNING *; DROPTABLE gtestm;
SELECT * FROM gtest1v; DELETEFROM gtest1v WHERE a >= 5; DROP VIEW gtest1v;
-- CTEs WITH foo AS (SELECT * FROM gtest1) SELECT * FROM foo;
-- inheritance CREATETABLE gtest1_1 () INHERITS (gtest1); SELECT * FROM gtest1_1;
\d gtest1_1 INSERTINTO gtest1_1 VALUES (4); SELECT * FROM gtest1_1; SELECT * FROM gtest1;
-- can't have generated column that is a child of normal column CREATETABLE gtest_normal (a int, b int); CREATETABLE gtest_normal_child (a int, b int GENERATED ALWAYS AS (a * 2) STORED) INHERITS (gtest_normal); -- error CREATETABLE gtest_normal_child (a int, b int GENERATED ALWAYS AS (a * 2) STORED); ALTERTABLE gtest_normal_child INHERIT gtest_normal; -- error DROPTABLE gtest_normal, gtest_normal_child;
-- test inheritance mismatches between parent and child CREATETABLE gtestx (x int, b intDEFAULT10) INHERITS (gtest1); -- error CREATETABLE gtestx (x int, b int GENERATED ALWAYS AS IDENTITY) INHERITS (gtest1); -- error CREATETABLE gtestx (x int, b int GENERATED ALWAYS AS (a * 22) VIRTUAL) INHERITS (gtest1); -- error CREATETABLE gtestx (x int, b int GENERATED ALWAYS AS (a * 22) STORED) INHERITS (gtest1); -- ok, overrides parent
\d+ gtestx INSERTINTO gtestx (a, x) VALUES (11, 22); SELECT * FROM gtest1; SELECT * FROM gtestx;
CREATETABLE gtestxx_1 (a intNOTNULL, b int); ALTERTABLE gtestxx_1 INHERIT gtest1; -- error CREATETABLE gtestxx_3 (a intNOTNULL, b int GENERATED ALWAYS AS (a * 2) STORED); ALTERTABLE gtestxx_3 INHERIT gtest1; -- ok CREATETABLE gtestxx_4 (b int GENERATED ALWAYS AS (a * 2) STORED, a intNOTNULL); ALTERTABLE gtestxx_4 INHERIT gtest1; -- ok
CREATETABLE gtesty (x int, b int GENERATED ALWAYS AS (x * 22) STORED); CREATETABLE gtest1_y () INHERITS (gtest1, gtesty); -- error CREATETABLE gtest1_y (b int GENERATED ALWAYS AS (x + 1) STORED) INHERITS (gtest1, gtesty); -- ok
\d gtest1_y
-- test correct handling of GENERATED column that's only in child CREATETABLE gtestp (f1 int); CREATETABLE gtestc (f2 int GENERATED ALWAYS AS (f1+1) STORED) INHERITS(gtestp); INSERTINTO gtestc values(42); TABLE gtestc; UPDATE gtestp SET f1 = f1 * 10; TABLE gtestc; DROPTABLE gtestp CASCADE;
-- test stored update CREATETABLE gtest3 (a int, b int GENERATED ALWAYS AS (a * 3) STORED); INSERTINTO gtest3 (a) VALUES (1), (2), (3), (NULL); SELECT * FROM gtest3 ORDERBY a; UPDATE gtest3 SET a = 22WHERE a = 2; SELECT * FROM gtest3 ORDERBY a;
CREATETABLE gtest3a (a text, b text GENERATED ALWAYS AS (a || '+' || a) STORED); INSERTINTO gtest3a (a) VALUES ('a'), ('b'), ('c'), (NULL); SELECT * FROM gtest3a ORDERBY a; UPDATE gtest3a SET a = 'bb'WHERE a = 'b'; SELECT * FROM gtest3a ORDERBY a;
-- null values CREATETABLE gtest2 (a intPRIMARYKEY, b int GENERATED ALWAYS AS (NULL) STORED); INSERTINTO gtest2 VALUES (1); SELECT * FROM gtest2;
-- simple column reference for varlena types CREATETABLE gtest_varlena (a varchar, b varchar GENERATED ALWAYS AS (a) STORED); INSERTINTO gtest_varlena (a) VALUES('01234567890123456789'); INSERTINTO gtest_varlena (a) VALUES(NULL); SELECT * FROM gtest_varlena ORDERBY a; DROPTABLE gtest_varlena;
-- composite types CREATE TYPE double_int as (a int, b int); CREATETABLE gtest4 (
a int,
b double_int GENERATED ALWAYS AS ((a * 2, a * 3)) STORED
); INSERTINTO gtest4 VALUES (1), (6); SELECT * FROM gtest4;
DROPTABLE gtest4; DROP TYPE double_int;
-- using tableoid is allowed CREATETABLE gtest_tableoid (
a intPRIMARYKEY,
b bool GENERATED ALWAYS AS (tableoid = 'gtest_tableoid'::regclass) STORED
); INSERTINTO gtest_tableoid VALUES (1), (2); ALTERTABLE gtest_tableoid ADDCOLUMN
c regclass GENERATED ALWAYS AS (tableoid) STORED; SELECT * FROM gtest_tableoid;
-- drop column behavior CREATETABLE gtest10 (a intPRIMARYKEY, b int, c int GENERATED ALWAYS AS (b * 2) STORED); ALTERTABLE gtest10 DROPCOLUMN b; -- fails ALTERTABLE gtest10 DROPCOLUMN b CASCADE; -- drops c too
\d gtest10
CREATETABLE gtest10a (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a * 2) STORED); ALTERTABLE gtest10a DROPCOLUMN b; INSERTINTO gtest10a (a) VALUES (1);
-- privileges CREATE USER regress_user11;
CREATETABLE gtest11 (a intPRIMARYKEY, b int, c int GENERATED ALWAYS AS (b * 2) STORED); INSERTINTO gtest11 VALUES (1, 10), (2, 20); GRANTSELECT (a, c) ON gtest11 TO regress_user11;
CREATE FUNCTION gf1(a int) RETURNS intAS $$ SELECT a * 3 $$ IMMUTABLE LANGUAGE SQL; REVOKEALLON FUNCTION gf1(int) FROM PUBLIC;
CREATETABLE gtest12 (a intPRIMARYKEY, b int, c int GENERATED ALWAYS AS (gf1(b)) STORED); INSERTINTO gtest12 VALUES (1, 10), (2, 20); GRANTSELECT (a, c), INSERTON gtest12 TO regress_user11;
SET ROLE regress_user11; SELECT a, b FROM gtest11; -- not allowed SELECT a, c FROM gtest11; -- allowed SELECT gf1(10); -- not allowed INSERTINTO gtest12 VALUES (3, 30), (4, 40); -- currently not allowed because of function permissions, should arguably be allowed SELECT a, c FROM gtest12; -- allowed (does not actually invoke the function)
RESET ROLE;
DROP FUNCTION gf1(int); -- fail DROPTABLE gtest11, gtest12; DROP FUNCTION gf1(int); DROP USER regress_user11;
-- check constraints CREATETABLE gtest20 (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a * 2) STORED CHECK (b < 50)); INSERTINTO gtest20 (a) VALUES (10); -- ok INSERTINTO gtest20 (a) VALUES (30); -- violates constraint
ALTERTABLE gtest20 ALTERCOLUMN b SET EXPRESSION AS (a * 100); -- violates constraint ALTERTABLE gtest20 ALTERCOLUMN b SET EXPRESSION AS (a * 3); -- ok
CREATETABLE gtest20a (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a * 2) STORED); INSERTINTO gtest20a (a) VALUES (10); INSERTINTO gtest20a (a) VALUES (30); ALTERTABLE gtest20a ADDCHECK (b < 50); -- fails on existing row -- table rewrite cases ALTERTABLE gtest20a ADDCOLUMN c float8DEFAULT random() CHECK (b < 50); -- fails on existing row ALTERTABLE gtest20a ADDCOLUMN c float8DEFAULT random() CHECK (b < 61); -- ok
CREATETABLE gtest20b (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a * 2) STORED); INSERTINTO gtest20b (a) VALUES (10); INSERTINTO gtest20b (a) VALUES (30); ALTERTABLE gtest20b ADDCONSTRAINT chk CHECK (b < 50) NOT VALID; ALTERTABLE gtest20b VALIDATE CONSTRAINT chk; -- fails on existing row
-- check with whole-row reference CREATETABLE gtest20c (a int, b int GENERATED ALWAYS AS (a * 2) STORED); ALTERTABLE gtest20c ADDCONSTRAINT whole_row_check CHECK (gtest20c ISNOTNULL); INSERTINTO gtest20c VALUES (1); -- ok INSERTINTO gtest20c VALUES (NULL); -- fails
-- not-null constraints CREATETABLE gtest21a (a intPRIMARYKEY, b int GENERATED ALWAYS AS (nullif(a, 0)) STORED NOTNULL); INSERTINTO gtest21a (a) VALUES (1); -- ok INSERTINTO gtest21a (a) VALUES (0); -- violates constraint
CREATETABLE gtest21b (a intPRIMARYKEY, b int GENERATED ALWAYS AS (nullif(a, 0)) STORED); ALTERTABLE gtest21b ALTERCOLUMN b SETNOTNULL; INSERTINTO gtest21b (a) VALUES (1); -- ok INSERTINTO gtest21b (a) VALUES (0); -- violates constraint ALTERTABLE gtest21b ALTERCOLUMN b DROPNOTNULL; INSERTINTO gtest21b (a) VALUES (0); -- ok now
-- index constraints CREATETABLE gtest22a (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a / 2) STORED UNIQUE); INSERTINTO gtest22a VALUES (2); INSERTINTO gtest22a VALUES (3); INSERTINTO gtest22a VALUES (4); CREATETABLE gtest22b (a int, b int GENERATED ALWAYS AS (a / 2) STORED, PRIMARYKEY (a, b)); INSERTINTO gtest22b VALUES (2); INSERTINTO gtest22b VALUES (2);
-- indexes CREATETABLE gtest22c (a int, b int GENERATED ALWAYS AS (a * 2) STORED); CREATEINDEX gtest22c_b_idx ON gtest22c (b); CREATEINDEX gtest22c_expr_idx ON gtest22c ((b * 3)); CREATEINDEX gtest22c_pred_idx ON gtest22c (a) WHERE b > 0;
\d gtest22c
INSERTINTO gtest22c VALUES (1), (2), (3); SET enable_seqscan TO off; SET enable_bitmapscan TO off; EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b = 4; SELECT * FROM gtest22c WHERE b = 4; EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b * 3 = 6; SELECT * FROM gtest22c WHERE b * 3 = 6; EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE a = 1AND b > 0; SELECT * FROM gtest22c WHERE a = 1AND b > 0;
ALTERTABLE gtest22c ALTERCOLUMN b SET EXPRESSION AS (a * 4); ANALYZE gtest22c; EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b = 8; SELECT * FROM gtest22c WHERE b = 8; EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE b * 3 = 12; SELECT * FROM gtest22c WHERE b * 3 = 12; EXPLAIN (COSTS OFF) SELECT * FROM gtest22c WHERE a = 1AND b > 0; SELECT * FROM gtest22c WHERE a = 1AND b > 0;
RESET enable_seqscan;
RESET enable_bitmapscan;
CREATETABLE gtest23x (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a * 2) STORED REFERENCES gtest23a (x) ONUPDATECASCADE); -- error CREATETABLE gtest23x (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a * 2) STORED REFERENCES gtest23a (x) ONDELETESETNULL); -- error
CREATETABLE gtest23b (a intPRIMARYKEY, b int GENERATED ALWAYS AS (a * 2) STORED REFERENCES gtest23a (x));
\d gtest23b
INSERTINTO gtest23b VALUES (1); -- ok INSERTINTO gtest23b VALUES (5); -- error ALTERTABLE gtest23b ALTERCOLUMN b SET EXPRESSION AS (a * 5); -- error ALTERTABLE gtest23b ALTERCOLUMN b SET EXPRESSION AS (a * 1); -- ok
DROPTABLE gtest23b; DROPTABLE gtest23a;
CREATETABLE gtest23p (x int, y int GENERATED ALWAYS AS (x * 2) STORED, PRIMARYKEY (y)); INSERTINTO gtest23p VALUES (1), (2), (3);
CREATETABLE gtest23q (a intPRIMARYKEY, b intREFERENCES gtest23p (y)); INSERTINTO gtest23q VALUES (1, 2); -- ok INSERTINTO gtest23q VALUES (2, 5); -- error
-- domains CREATE DOMAIN gtestdomain1 ASintCHECK (VALUE < 10); CREATETABLE gtest24 (a intPRIMARYKEY, b gtestdomain1 GENERATED ALWAYS AS (a * 2) STORED); INSERTINTO gtest24 (a) VALUES (4); -- ok INSERTINTO gtest24 (a) VALUES (6); -- error CREATE TYPE gtestdomain1range AS range (subtype = gtestdomain1); CREATETABLE gtest24r (a intPRIMARYKEY, b gtestdomain1range GENERATED ALWAYS AS (gtestdomain1range(a, a + 5)) STORED); INSERTINTO gtest24r (a) VALUES (4); -- ok INSERTINTO gtest24r (a) VALUES (6); -- error
CREATE DOMAIN gtestdomainnn ASintCHECK (VALUE ISNOTNULL); CREATETABLE gtest24nn (a int, b gtestdomainnn GENERATED ALWAYS AS (a * 2) STORED); INSERTINTO gtest24nn (a) VALUES (4); -- ok INSERTINTO gtest24nn (a) VALUES (NULL); -- error
-- typed tables (currently not supported) CREATE TYPE gtest_type AS (f1 integer, f2 text, f3 bigint); CREATETABLE gtest28 OF gtest_type (f1 WITH OPTIONS GENERATED ALWAYS AS (f2 *2) STORED); DROP TYPE gtest_type CASCADE;
-- partitioning cases CREATETABLE gtest_parent (f1 date NOTNULL, f2 bigint, f3 bigint) PARTITION BY RANGE (f1); CREATETABLE gtest_child PARTITION OF gtest_parent (
f3 WITH OPTIONS GENERATED ALWAYS AS (f2 * 2) STORED
) FORVALUESFROM ('2016-07-01') TO ('2016-08-01'); -- error CREATETABLE gtest_child (f1 date NOTNULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED); ALTERTABLE gtest_parent ATTACH PARTITION gtest_child FORVALUESFROM ('2016-07-01') TO ('2016-08-01'); -- error DROPTABLE gtest_parent, gtest_child;
CREATETABLE gtest_parent (f1 date NOTNULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE (f1); CREATETABLE gtest_child PARTITION OF gtest_parent FORVALUESFROM ('2016-07-01') TO ('2016-08-01'); -- inherits gen expr CREATETABLE gtest_child2 PARTITION OF gtest_parent (
f3 WITH OPTIONS GENERATED ALWAYS AS (f2 * 22) STORED -- overrides gen expr
) FORVALUESFROM ('2016-08-01') TO ('2016-09-01'); CREATETABLE gtest_child3 PARTITION OF gtest_parent (
f3 DEFAULT42-- error
) FORVALUESFROM ('2016-09-01') TO ('2016-10-01'); CREATETABLE gtest_child3 PARTITION OF gtest_parent (
f3 WITH OPTIONS GENERATED ALWAYS AS IDENTITY -- error
) FORVALUESFROM ('2016-09-01') TO ('2016-10-01'); CREATETABLE gtest_child3 PARTITION OF gtest_parent (
f3 GENERATED ALWAYS AS (f2 * 2) VIRTUAL -- error
) FORVALUESFROM ('2016-09-01') TO ('2016-10-01'); CREATETABLE gtest_child3 (f1 date NOTNULL, f2 bigint, f3 bigint); ALTERTABLE gtest_parent ATTACH PARTITION gtest_child3 FORVALUESFROM ('2016-09-01') TO ('2016-10-01'); -- error DROPTABLE gtest_child3; CREATETABLE gtest_child3 (f1 date NOTNULL, f2 bigint, f3 bigintDEFAULT42); ALTERTABLE gtest_parent ATTACH PARTITION gtest_child3 FORVALUESFROM ('2016-09-01') TO ('2016-10-01'); -- error DROPTABLE gtest_child3; CREATETABLE gtest_child3 (f1 date NOTNULL, f2 bigint, f3 bigint GENERATED ALWAYS AS IDENTITY); ALTERTABLE gtest_parent ATTACH PARTITION gtest_child3 FORVALUESFROM ('2016-09-01') TO ('2016-10-01'); -- error DROPTABLE gtest_child3; CREATETABLE gtest_child3 (f1 date NOTNULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) VIRTUAL); ALTERTABLE gtest_parent ATTACH PARTITION gtest_child3 FORVALUESFROM ('2016-09-01') TO ('2016-10-01'); -- error DROPTABLE gtest_child3; CREATETABLE gtest_child3 (f1 date NOTNULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 33) STORED); ALTERTABLE gtest_parent ATTACH PARTITION gtest_child3 FORVALUESFROM ('2016-09-01') TO ('2016-10-01');
\d gtest_child
\d gtest_child2
\d gtest_child3 INSERTINTO gtest_parent (f1, f2) VALUES ('2016-07-15', 1); INSERTINTO gtest_parent (f1, f2) VALUES ('2016-07-15', 2); INSERTINTO gtest_parent (f1, f2) VALUES ('2016-08-15', 3); SELECT tableoid::regclass, * FROM gtest_parent ORDERBY1, 2, 3; SELECT tableoid::regclass, * FROM gtest_child ORDERBY1, 2, 3; SELECT tableoid::regclass, * FROM gtest_child2 ORDERBY1, 2, 3; SELECT tableoid::regclass, * FROM gtest_child3 ORDERBY1, 2, 3; UPDATE gtest_parent SET f1 = f1 + 60WHERE f2 = 1; SELECT tableoid::regclass, * FROM gtest_parent ORDERBY1, 2, 3;
-- alter only parent's and one child's generation expression ALTERTABLE ONLY gtest_parent ALTERCOLUMN f3 SET EXPRESSION AS (f2 * 4); ALTERTABLE gtest_child ALTERCOLUMN f3 SET EXPRESSION AS (f2 * 10);
\d gtest_parent
\d gtest_child
\d gtest_child2
\d gtest_child3 SELECT tableoid::regclass, * FROM gtest_parent ORDERBY1, 2, 3;
-- alter generation expression of parent and all its children altogether ALTERTABLE gtest_parent ALTERCOLUMN f3 SET EXPRESSION AS (f2 * 2);
\d gtest_parent
\d gtest_child
\d gtest_child2
\d gtest_child3 SELECT tableoid::regclass, * FROM gtest_parent ORDERBY1, 2, 3; -- we leave these tables around for purposes of testing dump/reload/upgrade
-- generated columns in partition key (not allowed) CREATETABLE gtest_part_key (f1 date NOTNULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE (f3); CREATETABLE gtest_part_key (f1 date NOTNULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE ((f3)); CREATETABLE gtest_part_key (f1 date NOTNULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE ((f3 * 3)); CREATETABLE gtest_part_key (f1 date NOTNULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE ((gtest_part_key)); CREATETABLE gtest_part_key (f1 date NOTNULL, f2 bigint, f3 bigint GENERATED ALWAYS AS (f2 * 2) STORED) PARTITION BY RANGE ((gtest_part_key isnotnull));
-- ALTER TABLE ... ADD COLUMN CREATETABLE gtest25 (a intPRIMARYKEY); INSERTINTO gtest25 VALUES (3), (4); ALTERTABLE gtest25 ADDCOLUMN b int GENERATED ALWAYS AS (a * 2) STORED, ALTERCOLUMN b SET EXPRESSION AS (a * 3); SELECT * FROM gtest25 ORDERBY a; ALTERTABLE gtest25 ADDCOLUMN x int GENERATED ALWAYS AS (b * 4) STORED; -- error ALTERTABLE gtest25 ADDCOLUMN x int GENERATED ALWAYS AS (z * 4) STORED; -- error ALTERTABLE gtest25 ADDCOLUMN c intDEFAULT42, ADDCOLUMN x int GENERATED ALWAYS AS (c * 4) STORED; ALTERTABLE gtest25 ADDCOLUMN d intDEFAULT101; ALTERTABLE gtest25 ALTERCOLUMN d SET DATA TYPE float8, ADDCOLUMN y float8 GENERATED ALWAYS AS (d * 4) STORED; SELECT * FROM gtest25 ORDERBY a;
\d gtest25
-- ALTER TABLE ... ALTER COLUMN CREATETABLE gtest27 (
a int,
b int,
x int GENERATED ALWAYS AS ((a + b) * 2) STORED
); INSERTINTO gtest27 (a, b) VALUES (3, 7), (4, 11); ALTERTABLE gtest27 ALTERCOLUMN a TYPE text; -- error ALTERTABLE gtest27 ALTERCOLUMN x TYPE numeric;
\d gtest27 SELECT * FROM gtest27; ALTERTABLE gtest27 ALTERCOLUMN x TYPE boolean USING x <> 0; -- error ALTERTABLE gtest27 ALTERCOLUMN x DROPDEFAULT; -- error -- It's possible to alter the column types this way: ALTERTABLE gtest27 DROPCOLUMN x, ALTERCOLUMN a TYPE bigint, ALTERCOLUMN b TYPE bigint, ADDCOLUMN x bigint GENERATED ALWAYS AS ((a + b) * 2) STORED;
\d gtest27 -- Ideally you could just do this, but not today (and should x change type?): ALTERTABLE gtest27 ALTERCOLUMN a TYPE float8, ALTERCOLUMN b TYPE float8; -- error
\d gtest27 SELECT * FROM gtest27;
-- ALTER TABLE ... ALTER COLUMN ... DROP EXPRESSION CREATETABLE gtest29 (
a int,
b int GENERATED ALWAYS AS (a * 2) STORED
); INSERTINTO gtest29 (a) VALUES (3), (4); SELECT * FROM gtest29;
\d gtest29 ALTERTABLE gtest29 ALTERCOLUMN a SET EXPRESSION AS (a * 3); -- error ALTERTABLE gtest29 ALTERCOLUMN a DROP EXPRESSION; -- error ALTERTABLE gtest29 ALTERCOLUMN a DROP EXPRESSION IFEXISTS; -- notice
-- Change the expression ALTERTABLE gtest29 ALTERCOLUMN b SET EXPRESSION AS (a * 3); SELECT * FROM gtest29;
\d gtest29
ALTERTABLE gtest29 ALTERCOLUMN b DROP EXPRESSION; INSERTINTO gtest29 (a) VALUES (5); INSERTINTO gtest29 (a, b) VALUES (6, 66); SELECT * FROM gtest29;
\d gtest29
-- check that dependencies between columns have also been removed ALTERTABLE gtest29 DROPCOLUMN a; -- should not drop b
\d gtest29
-- with inheritance CREATETABLE gtest30 (
a int,
b int GENERATED ALWAYS AS (a * 2) STORED
); CREATETABLE gtest30_1 () INHERITS (gtest30); ALTERTABLE gtest30 ALTERCOLUMN b DROP EXPRESSION;
\d gtest30
\d gtest30_1 DROPTABLE gtest30 CASCADE; CREATETABLE gtest30 (
a int,
b int GENERATED ALWAYS AS (a * 2) STORED
); CREATETABLE gtest30_1 () INHERITS (gtest30); ALTERTABLE ONLY gtest30 ALTERCOLUMN b DROP EXPRESSION; -- error
\d gtest30
\d gtest30_1 ALTERTABLE gtest30_1 ALTERCOLUMN b DROP EXPRESSION; -- error
-- composite type dependencies CREATETABLE gtest31_1 (a int, b text GENERATED ALWAYS AS ('hello') STORED, c text); CREATETABLE gtest31_2 (x int, y gtest31_1); ALTERTABLE gtest31_1 ALTERCOLUMN b TYPE varchar; -- fails
-- bug #18970: these cases are unsupported, but make sure they fail cleanly ALTERTABLE gtest31_2 ADDCONSTRAINT cc CHECK ((y).b ISNOTNULL); ALTERTABLE gtest31_1 ALTERCOLUMN b SET EXPRESSION AS ('hello1'); ALTERTABLE gtest31_2 DROPCONSTRAINT cc;
CREATE STATISTICS gtest31_2_stat ON ((y).b isnotnull) FROM gtest31_2; ALTERTABLE gtest31_1 ALTERCOLUMN b SET EXPRESSION AS ('hello2'); DROP STATISTICS gtest31_2_stat;
CREATEINDEX gtest31_2_y_idx ON gtest31_2(((y).b)); ALTERTABLE gtest31_1 ALTERCOLUMN b SET EXPRESSION AS ('hello3');
DROPTABLE gtest31_1, gtest31_2;
-- Check it for a partitioned table, too CREATETABLE gtest31_1 (a int, b text GENERATED ALWAYS AS ('hello') STORED, c text) PARTITION BY LIST (a); CREATETABLE gtest31_2 (x int, y gtest31_1); ALTERTABLE gtest31_1 ALTERCOLUMN b TYPE varchar; -- fails DROPTABLE gtest31_1, gtest31_2;
-- triggers CREATETABLE gtest26 (
a intPRIMARYKEY,
b int GENERATED ALWAYS AS (a * 2) STORED
);
CREATE FUNCTION gtest_trigger_func() RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN IF tg_op IN ('DELETE', 'UPDATE') THEN
RAISE INFO '%: %: old = %', TG_NAME, TG_WHEN, OLD;
END IF; IF tg_op IN ('INSERT', 'UPDATE') THEN
RAISE INFO '%: %: new = %', TG_NAME, TG_WHEN, NEW;
END IF; IF tg_op = 'DELETE'THEN RETURN OLD; ELSE RETURN NEW;
END IF;
END
$$;
CREATETRIGGER gtest1 BEFOREDELETEORUPDATEON gtest26 FOREACH ROW WHEN (OLD.b < 0) -- ok
EXECUTE PROCEDURE gtest_trigger_func();
CREATETRIGGER gtest3 AFTER DELETEORUPDATEON gtest26 FOREACH ROW WHEN (OLD.b < 0) -- ok
EXECUTE PROCEDURE gtest_trigger_func();
CREATETRIGGER gtest4 AFTER INSERTORUPDATEON gtest26 FOREACH ROW WHEN (NEW.b < 0) -- ok
EXECUTE PROCEDURE gtest_trigger_func();
INSERTINTO gtest26 (a) VALUES (-2), (0), (3); SELECT * FROM gtest26 ORDERBY a; UPDATE gtest26 SET a = a * -2; SELECT * FROM gtest26 ORDERBY a; DELETEFROM gtest26 WHERE a = -6; SELECT * FROM gtest26 ORDERBY a;
DROPTRIGGER gtest1 ON gtest26; DROPTRIGGER gtest2 ON gtest26; DROPTRIGGER gtest3 ON gtest26;
-- Check that an UPDATE of "a" fires the trigger for UPDATE OF b, per -- SQL standard. CREATE FUNCTION gtest_trigger_func3() RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE NOTICE 'OK'; RETURN NEW;
END
$$;
CREATETRIGGER gtest11 BEFOREUPDATE OF b ON gtest26 FOREACH ROW
EXECUTE PROCEDURE gtest_trigger_func3();
UPDATE gtest26 SET a = 1WHERE a = 0;
DROPTRIGGER gtest11 ON gtest26;
TRUNCATE gtest26;
-- check that modifications of generated columns in triggers do -- not get propagated CREATE FUNCTION gtest_trigger_func4() RETURNS trigger
LANGUAGE plpgsql AS $$
BEGIN
NEW.a = 10;
NEW.b = 300; RETURN NEW;
END;
$$;
INSERTINTO gtest26 (a) VALUES (1); SELECT * FROM gtest26 ORDERBY a; UPDATE gtest26 SET a = 11WHERE a = 10; SELECT * FROM gtest26 ORDERBY a;
-- LIKE INCLUDING GENERATED and dropped column handling CREATETABLE gtest28a (
a int,
b int,
c int,
x int GENERATED ALWAYS AS (b * 2) STORED
);
ALTERTABLE gtest28a DROPCOLUMN a;
CREATETABLE gtest28b (LIKE gtest28a INCLUDING GENERATED);
\d gtest28*
-- rule actions referring to generated columns: -- NEW.b in a rule action should reflect the generated column's new value CREATETABLE gtest_rule (a int, b int GENERATED ALWAYS AS (a * 2) STORED); CREATETABLE gtest_rule_log (op text, old_b int, new_b int); CREATE RULE gtest_rule_upd ASONUPDATETO gtest_rule
DO ALSO INSERTINTO gtest_rule_log VALUES ('UPD', OLD.b, NEW.b); CREATE RULE gtest_rule_ins ASONINSERTTO gtest_rule
DO ALSO INSERTINTO gtest_rule_log VALUES ('INS', NULL, NEW.b); INSERTINTO gtest_rule (a) VALUES (1); UPDATE gtest_rule SET a = 10; UPDATE gtest_rule SET a = (SELECT max(b) FROM gtest_rule); SELECT * FROM gtest_rule_log; DROP RULE gtest_rule_upd ON gtest_rule; DROP RULE gtest_rule_ins ON gtest_rule; DROPTABLE gtest_rule_log;
-- rule quals referring to generated columns: -- NEW.b in the rule qual should reflect the generated column's new value CREATE RULE gtest_rule_qual ASONUPDATETO gtest_rule WHERE NEW.b > 100
DO INSTEAD NOTHING; UPDATE gtest_rule SET a = 100; SELECT * FROM gtest_rule; DROPTABLE gtest_rule;
-- sanity check of system catalog SELECT attrelid, attname, attgenerated FROM pg_attribute WHERE attgenerated NOTIN ('', 's', 'v');
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.3 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.