Merge pull request #18 from percona/TDE_EXP_FILES_1075

Add TDE support and update expected files for tde_heap & tde_heap_basic
pull/209/head
Naeem Akhter 10 months ago committed by GitHub
commit 5ad99f77be
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 578
      src/test/regress/expected/create_am_1.out
  2. 3000
      src/test/regress/expected/create_index_1.out
  3. 3000
      src/test/regress/expected/create_index_2.out
  4. 744
      src/test/regress/expected/event_trigger_1.out
  5. 6736
      src/test/regress/expected/psql_1.out
  6. 26
      src/test/regress/pg_regress.c

@ -0,0 +1,578 @@
--
-- Create access method tests
--
-- Make gist2 over gisthandler. In fact, it would be a synonym to gist.
CREATE ACCESS METHOD gist2 TYPE INDEX HANDLER gisthandler;
-- Verify return type checks for handlers
CREATE ACCESS METHOD bogus TYPE INDEX HANDLER int4in;
ERROR: function int4in(internal) does not exist
CREATE ACCESS METHOD bogus TYPE INDEX HANDLER heap_tableam_handler;
ERROR: function heap_tableam_handler must return type index_am_handler
-- Try to create gist2 index on fast_emp4000: fail because opclass doesn't exist
CREATE INDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base);
ERROR: data type box has no default operator class for access method "gist2"
HINT: You must specify an operator class for the index or define a default operator class for the data type.
-- Make operator class for boxes using gist2
CREATE OPERATOR CLASS box_ops DEFAULT
FOR TYPE box USING gist2 AS
OPERATOR 1 <<,
OPERATOR 2 &<,
OPERATOR 3 &&,
OPERATOR 4 &>,
OPERATOR 5 >>,
OPERATOR 6 ~=,
OPERATOR 7 @>,
OPERATOR 8 <@,
OPERATOR 9 &<|,
OPERATOR 10 <<|,
OPERATOR 11 |>>,
OPERATOR 12 |&>,
FUNCTION 1 gist_box_consistent(internal, box, smallint, oid, internal),
FUNCTION 2 gist_box_union(internal, internal),
-- don't need compress, decompress, or fetch functions
FUNCTION 5 gist_box_penalty(internal, internal, internal),
FUNCTION 6 gist_box_picksplit(internal, internal),
FUNCTION 7 gist_box_same(box, box, internal);
-- Create gist2 index on fast_emp4000
CREATE INDEX grect2ind2 ON fast_emp4000 USING gist2 (home_base);
-- Now check the results from plain indexscan; temporarily drop existing
-- index grect2ind to ensure it doesn't capture the plan
BEGIN;
DROP INDEX grect2ind;
SET enable_seqscan = OFF;
SET enable_indexscan = ON;
SET enable_bitmapscan = OFF;
EXPLAIN (COSTS OFF)
SELECT * FROM fast_emp4000
WHERE home_base <@ '(200,200),(2000,1000)'::box
ORDER BY (home_base[0])[0];
QUERY PLAN
-----------------------------------------------------------------
Sort
Sort Key: ((home_base[0])[0])
-> Index Only Scan using grect2ind2 on fast_emp4000
Index Cond: (home_base <@ '(2000,1000),(200,200)'::box)
(4 rows)
SELECT * FROM fast_emp4000
WHERE home_base <@ '(200,200),(2000,1000)'::box
ORDER BY (home_base[0])[0];
home_base
-----------------------
(337,455),(240,359)
(1444,403),(1346,344)
(2 rows)
EXPLAIN (COSTS OFF)
SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
QUERY PLAN
-------------------------------------------------------------
Aggregate
-> Index Only Scan using grect2ind2 on fast_emp4000
Index Cond: (home_base && '(1000,1000),(0,0)'::box)
(3 rows)
SELECT count(*) FROM fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box;
count
-------
2
(1 row)
EXPLAIN (COSTS OFF)
SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL;
QUERY PLAN
--------------------------------------------------------
Aggregate
-> Index Only Scan using grect2ind2 on fast_emp4000
Index Cond: (home_base IS NULL)
(3 rows)
SELECT count(*) FROM fast_emp4000 WHERE home_base IS NULL;
count
-------
278
(1 row)
ROLLBACK;
-- Try to drop access method: fail because of dependent objects
DROP ACCESS METHOD gist2;
ERROR: cannot drop access method gist2 because other objects depend on it
DETAIL: index grect2ind2 depends on operator class box_ops for access method gist2
HINT: Use DROP ... CASCADE to drop the dependent objects too.
-- Drop access method cascade
-- To prevent a (rare) deadlock against autovacuum,
-- we must lock the table that owns the index that will be dropped
BEGIN;
LOCK TABLE fast_emp4000;
DROP ACCESS METHOD gist2 CASCADE;
NOTICE: drop cascades to index grect2ind2
COMMIT;
--
-- Test table access methods
--
-- prevent empty values
SET default_table_access_method = '';
ERROR: invalid value for parameter "default_table_access_method": ""
DETAIL: "default_table_access_method" cannot be empty.
-- prevent nonexistent values
SET default_table_access_method = 'I do not exist AM';
ERROR: invalid value for parameter "default_table_access_method": "I do not exist AM"
DETAIL: Table access method "I do not exist AM" does not exist.
-- prevent setting it to an index AM
SET default_table_access_method = 'btree';
ERROR: access method "btree" is not of type TABLE
-- Create a heap2 table am handler with heapam handler
CREATE ACCESS METHOD heap2 TYPE TABLE HANDLER heap_tableam_handler;
-- Verify return type checks for handlers
CREATE ACCESS METHOD bogus TYPE TABLE HANDLER int4in;
ERROR: function int4in(internal) does not exist
CREATE ACCESS METHOD bogus TYPE TABLE HANDLER bthandler;
ERROR: function bthandler must return type table_am_handler
SELECT amname, amhandler, amtype FROM pg_am where amtype = 't' ORDER BY 1, 2;
amname | amhandler | amtype
----------------+------------------------+--------
heap | heap_tableam_handler | t
heap2 | heap_tableam_handler | t
tde_heap | pg_tdeam_handler | t
tde_heap_basic | pg_tdeam_basic_handler | t
(4 rows)
-- First create tables employing the new AM using USING
-- plain CREATE TABLE
CREATE TABLE tableam_tbl_heap2(f1 int) USING heap2;
INSERT INTO tableam_tbl_heap2 VALUES(1);
SELECT f1 FROM tableam_tbl_heap2 ORDER BY f1;
f1
----
1
(1 row)
-- CREATE TABLE AS
CREATE TABLE tableam_tblas_heap2 USING heap2 AS SELECT * FROM tableam_tbl_heap2;
SELECT f1 FROM tableam_tbl_heap2 ORDER BY f1;
f1
----
1
(1 row)
-- SELECT INTO doesn't support USING
SELECT INTO tableam_tblselectinto_heap2 USING heap2 FROM tableam_tbl_heap2;
ERROR: syntax error at or near "USING"
LINE 1: SELECT INTO tableam_tblselectinto_heap2 USING heap2 FROM tab...
^
-- CREATE VIEW doesn't support USING
CREATE VIEW tableam_view_heap2 USING heap2 AS SELECT * FROM tableam_tbl_heap2;
ERROR: syntax error at or near "USING"
LINE 1: CREATE VIEW tableam_view_heap2 USING heap2 AS SELECT * FROM ...
^
-- CREATE SEQUENCE doesn't support USING
CREATE SEQUENCE tableam_seq_heap2 USING heap2;
ERROR: syntax error at or near "USING"
LINE 1: CREATE SEQUENCE tableam_seq_heap2 USING heap2;
^
-- CREATE MATERIALIZED VIEW does support USING
CREATE MATERIALIZED VIEW tableam_tblmv_heap2 USING heap2 AS SELECT * FROM tableam_tbl_heap2;
SELECT f1 FROM tableam_tblmv_heap2 ORDER BY f1;
f1
----
1
(1 row)
-- CREATE TABLE .. PARTITION BY supports USING.
CREATE TABLE tableam_parted_heap2 (a text, b int) PARTITION BY list (a) USING heap2;
SELECT a.amname FROM pg_class c, pg_am a
WHERE c.relname = 'tableam_parted_heap2' AND a.oid = c.relam;
amname
--------
heap2
(1 row)
DROP TABLE tableam_parted_heap2;
CREATE TABLE tableam_parted_heap2 (a text, b int) PARTITION BY list (a);
-- new partitions will inherit from the current default, rather the partition root
SET default_table_access_method = 'heap';
CREATE TABLE tableam_parted_a_heap2 PARTITION OF tableam_parted_heap2 FOR VALUES IN ('a');
SET default_table_access_method = 'heap2';
CREATE TABLE tableam_parted_b_heap2 PARTITION OF tableam_parted_heap2 FOR VALUES IN ('b');
RESET default_table_access_method;
-- but the method can be explicitly specified
CREATE TABLE tableam_parted_c_heap2 PARTITION OF tableam_parted_heap2 FOR VALUES IN ('c') USING heap;
CREATE TABLE tableam_parted_d_heap2 PARTITION OF tableam_parted_heap2 FOR VALUES IN ('d') USING heap2;
-- List all objects in AM
SELECT
pc.relkind,
pa.amname,
CASE WHEN relkind = 't' THEN
(SELECT 'toast for ' || relname::regclass FROM pg_class pcm WHERE pcm.reltoastrelid = pc.oid)
ELSE
relname::regclass::text
END COLLATE "C" AS relname
FROM pg_class AS pc,
pg_am AS pa
WHERE pa.oid = pc.relam
AND pa.amname = 'heap2'
ORDER BY 3, 1, 2;
relkind | amname | relname
---------+--------+----------------------------------
r | heap2 | tableam_parted_b_heap2
r | heap2 | tableam_parted_d_heap2
r | heap2 | tableam_tbl_heap2
r | heap2 | tableam_tblas_heap2
m | heap2 | tableam_tblmv_heap2
t | heap2 | toast for tableam_parted_b_heap2
t | heap2 | toast for tableam_parted_d_heap2
(7 rows)
-- Show dependencies onto AM - there shouldn't be any for toast
SELECT pg_describe_object(classid,objid,objsubid) AS obj
FROM pg_depend, pg_am
WHERE pg_depend.refclassid = 'pg_am'::regclass
AND pg_am.oid = pg_depend.refobjid
AND pg_am.amname = 'heap2'
ORDER BY classid, objid, objsubid;
obj
---------------------------------------
table tableam_tbl_heap2
table tableam_tblas_heap2
materialized view tableam_tblmv_heap2
table tableam_parted_b_heap2
table tableam_parted_d_heap2
(5 rows)
-- ALTER TABLE SET ACCESS METHOD
CREATE TABLE heaptable USING heap AS
SELECT a, repeat(a::text, 100) FROM generate_series(1,9) AS a;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass;
amname
--------
heap
(1 row)
-- Switching to heap2 adds new dependency entry to the AM.
ALTER TABLE heaptable SET ACCESS METHOD heap2;
SELECT pg_describe_object(classid, objid, objsubid) as obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as objref,
deptype
FROM pg_depend
WHERE classid = 'pg_class'::regclass AND
objid = 'heaptable'::regclass
ORDER BY 1, 2;
obj | objref | deptype
-----------------+---------------------+---------
table heaptable | access method heap2 | n
table heaptable | schema public | n
(2 rows)
-- Switching to heap should not have a dependency entry to the AM.
ALTER TABLE heaptable SET ACCESS METHOD heap;
SELECT pg_describe_object(classid, objid, objsubid) as obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as objref,
deptype
FROM pg_depend
WHERE classid = 'pg_class'::regclass AND
objid = 'heaptable'::regclass
ORDER BY 1, 2;
obj | objref | deptype
-----------------+---------------+---------
table heaptable | schema public | n
(1 row)
ALTER TABLE heaptable SET ACCESS METHOD heap2;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass;
amname
--------
heap2
(1 row)
SELECT COUNT(a), COUNT(1) FILTER(WHERE a=1) FROM heaptable;
count | count
-------+-------
9 | 1
(1 row)
-- DEFAULT access method
BEGIN;
SET LOCAL default_table_access_method TO heap2;
ALTER TABLE heaptable SET ACCESS METHOD DEFAULT;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass;
amname
--------
heap2
(1 row)
SET LOCAL default_table_access_method TO heap;
ALTER TABLE heaptable SET ACCESS METHOD DEFAULT;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heaptable'::regclass;
amname
--------
heap
(1 row)
ROLLBACK;
-- ALTER MATERIALIZED VIEW SET ACCESS METHOD
CREATE MATERIALIZED VIEW heapmv USING heap AS SELECT * FROM heaptable;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heapmv'::regclass;
amname
--------
heap
(1 row)
ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap2;
SELECT amname FROM pg_class c, pg_am am
WHERE c.relam = am.oid AND c.oid = 'heapmv'::regclass;
amname
--------
heap2
(1 row)
SELECT COUNT(a), COUNT(1) FILTER(WHERE a=1) FROM heapmv;
count | count
-------+-------
9 | 1
(1 row)
-- No support for multiple subcommands
ALTER TABLE heaptable SET ACCESS METHOD heap, SET ACCESS METHOD heap2;
ERROR: cannot have multiple SET ACCESS METHOD subcommands
ALTER TABLE heaptable SET ACCESS METHOD DEFAULT, SET ACCESS METHOD heap2;
ERROR: cannot have multiple SET ACCESS METHOD subcommands
ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap, SET ACCESS METHOD heap2;
ERROR: cannot have multiple SET ACCESS METHOD subcommands
DROP MATERIALIZED VIEW heapmv;
DROP TABLE heaptable;
-- Partitioned table with USING
CREATE TABLE am_partitioned(x INT, y INT) PARTITION BY hash (x) USING heap2;
SELECT pg_describe_object(classid, objid, objsubid) AS obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as refobj
FROM pg_depend, pg_am
WHERE pg_depend.refclassid = 'pg_am'::regclass
AND pg_am.oid = pg_depend.refobjid
AND pg_depend.objid = 'am_partitioned'::regclass;
obj | refobj
----------------------+---------------------
table am_partitioned | access method heap2
(1 row)
DROP TABLE am_partitioned;
-- Partition hierarchies with access methods
BEGIN;
SET LOCAL default_table_access_method = 'heap';
CREATE TABLE am_partitioned(x INT, y INT) PARTITION BY hash (x);
-- pg_class.relam is 0, no dependency recorded between the AM and the
-- partitioned table.
SELECT relam FROM pg_class WHERE relname = 'am_partitioned';
relam
-------
0
(1 row)
SELECT pg_describe_object(classid, objid, objsubid) AS obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as refobj
FROM pg_depend, pg_am
WHERE pg_depend.refclassid = 'pg_am'::regclass
AND pg_am.oid = pg_depend.refobjid
AND pg_depend.objid = 'am_partitioned'::regclass;
obj | refobj
-----+--------
(0 rows)
-- New default is set, with dependency added.
ALTER TABLE am_partitioned SET ACCESS METHOD heap2;
SELECT a.amname FROM pg_class c, pg_am a
WHERE c.relname = 'am_partitioned' AND a.oid = c.relam;
amname
--------
heap2
(1 row)
SELECT pg_describe_object(classid, objid, objsubid) AS obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as refobj
FROM pg_depend, pg_am
WHERE pg_depend.refclassid = 'pg_am'::regclass
AND pg_am.oid = pg_depend.refobjid
AND pg_depend.objid = 'am_partitioned'::regclass;
obj | refobj
----------------------+---------------------
table am_partitioned | access method heap2
(1 row)
-- Default is set, with dependency updated.
SET LOCAL default_table_access_method = 'heap2';
ALTER TABLE am_partitioned SET ACCESS METHOD heap;
SELECT a.amname FROM pg_class c, pg_am a
WHERE c.relname = 'am_partitioned' AND a.oid = c.relam;
amname
--------
heap
(1 row)
-- Dependency pinned, hence removed.
SELECT pg_describe_object(classid, objid, objsubid) AS obj,
pg_describe_object(refclassid, refobjid, refobjsubid) as refobj
FROM pg_depend, pg_am
WHERE pg_depend.refclassid = 'pg_am'::regclass
AND pg_am.oid = pg_depend.refobjid
AND pg_depend.objid = 'am_partitioned'::regclass;
obj | refobj
-----+--------
(0 rows)
-- Default and AM set in the clause are the same, relam should be set.
SET LOCAL default_table_access_method = 'heap2';
ALTER TABLE am_partitioned SET ACCESS METHOD heap2;
SELECT a.amname FROM pg_class c, pg_am a
WHERE c.relname = 'am_partitioned' AND a.oid = c.relam;
amname
--------
heap2
(1 row)
-- Reset to default
ALTER TABLE am_partitioned SET ACCESS METHOD DEFAULT;
SELECT relam FROM pg_class WHERE relname = 'am_partitioned';
relam
-------
0
(1 row)
-- Upon ALTER TABLE SET ACCESS METHOD on a partitioned table, new partitions
-- will inherit the AM set. Existing partitioned are unchanged.
SELECT relam FROM pg_class WHERE relname = 'am_partitioned';
relam
-------
0
(1 row)
SET LOCAL default_table_access_method = 'heap';
CREATE TABLE am_partitioned_0 PARTITION OF am_partitioned
FOR VALUES WITH (MODULUS 10, REMAINDER 0);
SET LOCAL default_table_access_method = 'heap2';
CREATE TABLE am_partitioned_1 PARTITION OF am_partitioned
FOR VALUES WITH (MODULUS 10, REMAINDER 1);
SET LOCAL default_table_access_method = 'heap';
ALTER TABLE am_partitioned SET ACCESS METHOD heap2;
CREATE TABLE am_partitioned_2 PARTITION OF am_partitioned
FOR VALUES WITH (MODULUS 10, REMAINDER 2);
ALTER TABLE am_partitioned SET ACCESS METHOD DEFAULT;
SELECT relam FROM pg_class WHERE relname = 'am_partitioned';
relam
-------
0
(1 row)
CREATE TABLE am_partitioned_3 PARTITION OF am_partitioned
FOR VALUES WITH (MODULUS 10, REMAINDER 3);
-- Partitioned table with relam at 0
ALTER TABLE am_partitioned SET ACCESS METHOD DEFAULT;
CREATE TABLE am_partitioned_5p PARTITION OF am_partitioned
FOR VALUES WITH (MODULUS 10, REMAINDER 5) PARTITION BY hash(y);
-- Partitions of this partitioned table inherit default AM at creation
-- time.
CREATE TABLE am_partitioned_5p1 PARTITION OF am_partitioned_5p
FOR VALUES WITH (MODULUS 10, REMAINDER 1);
-- Partitioned table with relam set.
ALTER TABLE am_partitioned SET ACCESS METHOD heap2;
CREATE TABLE am_partitioned_6p PARTITION OF am_partitioned
FOR VALUES WITH (MODULUS 10, REMAINDER 6) PARTITION BY hash(y);
-- Partitions of this partitioned table inherit its AM.
CREATE TABLE am_partitioned_6p1 PARTITION OF am_partitioned_6p
FOR VALUES WITH (MODULUS 10, REMAINDER 1);
SELECT c.relname, a.amname FROM pg_class c, pg_am a
WHERE c.relam = a.oid AND
c.relname LIKE 'am_partitioned%'
UNION ALL
SELECT c.relname, 'default' FROM pg_class c
WHERE c.relam = 0
AND c.relname LIKE 'am_partitioned%' ORDER BY 1;
relname | amname
--------------------+---------
am_partitioned | heap2
am_partitioned_0 | heap
am_partitioned_1 | heap2
am_partitioned_2 | heap2
am_partitioned_3 | heap
am_partitioned_5p | default
am_partitioned_5p1 | heap
am_partitioned_6p | heap2
am_partitioned_6p1 | heap2
(9 rows)
DROP TABLE am_partitioned;
COMMIT;
-- Second, create objects in the new AM by changing the default AM
BEGIN;
SET LOCAL default_table_access_method = 'heap2';
-- following tests should all respect the default AM
CREATE TABLE tableam_tbl_heapx(f1 int);
CREATE TABLE tableam_tblas_heapx AS SELECT * FROM tableam_tbl_heapx;
SELECT INTO tableam_tblselectinto_heapx FROM tableam_tbl_heapx;
CREATE MATERIALIZED VIEW tableam_tblmv_heapx USING heap2 AS SELECT * FROM tableam_tbl_heapx;
CREATE TABLE tableam_parted_heapx (a text, b int) PARTITION BY list (a);
CREATE TABLE tableam_parted_1_heapx PARTITION OF tableam_parted_heapx FOR VALUES IN ('a', 'b');
-- but an explicitly set AM overrides it
CREATE TABLE tableam_parted_2_heapx PARTITION OF tableam_parted_heapx FOR VALUES IN ('c', 'd') USING heap;
-- sequences, views and foreign servers shouldn't have an AM
CREATE VIEW tableam_view_heapx AS SELECT * FROM tableam_tbl_heapx;
CREATE SEQUENCE tableam_seq_heapx;
CREATE FOREIGN DATA WRAPPER fdw_heap2 VALIDATOR postgresql_fdw_validator;
CREATE SERVER fs_heap2 FOREIGN DATA WRAPPER fdw_heap2 ;
CREATE FOREIGN table tableam_fdw_heapx () SERVER fs_heap2;
-- Verify that new AM was used for tables, matviews, but not for sequences, views and fdws
SELECT
pc.relkind,
pa.amname,
CASE WHEN relkind = 't' THEN
(SELECT 'toast for ' || relname::regclass FROM pg_class pcm WHERE pcm.reltoastrelid = pc.oid)
ELSE
relname::regclass::text
END COLLATE "C" AS relname
FROM pg_class AS pc
LEFT JOIN pg_am AS pa ON (pa.oid = pc.relam)
WHERE pc.relname LIKE 'tableam_%_heapx'
ORDER BY 3, 1, 2;
relkind | amname | relname
---------+--------+-----------------------------
f | | tableam_fdw_heapx
r | heap2 | tableam_parted_1_heapx
r | heap | tableam_parted_2_heapx
p | | tableam_parted_heapx
S | | tableam_seq_heapx
r | heap2 | tableam_tbl_heapx
r | heap2 | tableam_tblas_heapx
m | heap2 | tableam_tblmv_heapx
r | heap2 | tableam_tblselectinto_heapx
v | | tableam_view_heapx
(10 rows)
-- don't want to keep those tables, nor the default
ROLLBACK;
-- Third, check that we can neither create a table using a nonexistent
-- AM, nor using an index AM
CREATE TABLE i_am_a_failure() USING "";
ERROR: zero-length delimited identifier at or near """"
LINE 1: CREATE TABLE i_am_a_failure() USING "";
^
CREATE TABLE i_am_a_failure() USING i_do_not_exist_am;
ERROR: access method "i_do_not_exist_am" does not exist
CREATE TABLE i_am_a_failure() USING "I do not exist AM";
ERROR: access method "I do not exist AM" does not exist
CREATE TABLE i_am_a_failure() USING "btree";
ERROR: access method "btree" is not of type TABLE
-- Other weird invalid cases that cause problems
CREATE FOREIGN TABLE fp PARTITION OF tableam_parted_a_heap2 DEFAULT SERVER x;
ERROR: "tableam_parted_a_heap2" is not partitioned
-- Drop table access method, which fails as objects depends on it
DROP ACCESS METHOD heap2;
ERROR: cannot drop access method heap2 because other objects depend on it
DETAIL: table tableam_tbl_heap2 depends on access method heap2
table tableam_tblas_heap2 depends on access method heap2
materialized view tableam_tblmv_heap2 depends on access method heap2
table tableam_parted_b_heap2 depends on access method heap2
table tableam_parted_d_heap2 depends on access method heap2
HINT: Use DROP ... CASCADE to drop the dependent objects too.
-- we intentionally leave the objects created above alive, to verify pg_dump support

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

@ -0,0 +1,744 @@
-- should fail, return type mismatch
create event trigger regress_event_trigger
on ddl_command_start
execute procedure pg_backend_pid();
ERROR: function pg_backend_pid must return type event_trigger
-- OK
create function test_event_trigger() returns event_trigger as $$
BEGIN
RAISE NOTICE 'test_event_trigger: % %', tg_event, tg_tag;
END
$$ language plpgsql;
-- should fail, can't call it as a plain function
SELECT test_event_trigger();
ERROR: trigger functions can only be called as triggers
CONTEXT: compilation of PL/pgSQL function "test_event_trigger" near line 1
-- should fail, event triggers cannot have declared arguments
create function test_event_trigger_arg(name text)
returns event_trigger as $$ BEGIN RETURN 1; END $$ language plpgsql;
ERROR: event trigger functions cannot have declared arguments
CONTEXT: compilation of PL/pgSQL function "test_event_trigger_arg" near line 1
-- should fail, SQL functions cannot be event triggers
create function test_event_trigger_sql() returns event_trigger as $$
SELECT 1 $$ language sql;
ERROR: SQL functions cannot return type event_trigger
-- should fail, no elephant_bootstrap entry point
create event trigger regress_event_trigger on elephant_bootstrap
execute procedure test_event_trigger();
ERROR: unrecognized event name "elephant_bootstrap"
-- OK
create event trigger regress_event_trigger on ddl_command_start
execute procedure test_event_trigger();
-- OK
create event trigger regress_event_trigger_end on ddl_command_end
execute function test_event_trigger();
-- should fail, food is not a valid filter variable
create event trigger regress_event_trigger2 on ddl_command_start
when food in ('sandwich')
execute procedure test_event_trigger();
ERROR: unrecognized filter variable "food"
-- should fail, sandwich is not a valid command tag
create event trigger regress_event_trigger2 on ddl_command_start
when tag in ('sandwich')
execute procedure test_event_trigger();
ERROR: filter value "sandwich" not recognized for filter variable "tag"
-- should fail, create skunkcabbage is not a valid command tag
create event trigger regress_event_trigger2 on ddl_command_start
when tag in ('create table', 'create skunkcabbage')
execute procedure test_event_trigger();
ERROR: filter value "create skunkcabbage" not recognized for filter variable "tag"
-- should fail, can't have event triggers on event triggers
create event trigger regress_event_trigger2 on ddl_command_start
when tag in ('DROP EVENT TRIGGER')
execute procedure test_event_trigger();
ERROR: event triggers are not supported for DROP EVENT TRIGGER
-- should fail, can't have event triggers on global objects
create event trigger regress_event_trigger2 on ddl_command_start
when tag in ('CREATE ROLE')
execute procedure test_event_trigger();
ERROR: event triggers are not supported for CREATE ROLE
-- should fail, can't have event triggers on global objects
create event trigger regress_event_trigger2 on ddl_command_start
when tag in ('CREATE DATABASE')
execute procedure test_event_trigger();
ERROR: event triggers are not supported for CREATE DATABASE
-- should fail, can't have event triggers on global objects
create event trigger regress_event_trigger2 on ddl_command_start
when tag in ('CREATE TABLESPACE')
execute procedure test_event_trigger();
ERROR: event triggers are not supported for CREATE TABLESPACE
-- should fail, can't have same filter variable twice
create event trigger regress_event_trigger2 on ddl_command_start
when tag in ('create table') and tag in ('CREATE FUNCTION')
execute procedure test_event_trigger();
ERROR: filter variable "tag" specified more than once
-- should fail, can't have arguments
create event trigger regress_event_trigger2 on ddl_command_start
execute procedure test_event_trigger('argument not allowed');
ERROR: syntax error at or near "'argument not allowed'"
LINE 2: execute procedure test_event_trigger('argument not allowe...
^
-- OK
create event trigger regress_event_trigger2 on ddl_command_start
when tag in ('create table', 'CREATE FUNCTION')
execute procedure test_event_trigger();
-- OK
comment on event trigger regress_event_trigger is 'test comment';
-- drop as non-superuser should fail
create role regress_evt_user;
set role regress_evt_user;
create event trigger regress_event_trigger_noperms on ddl_command_start
execute procedure test_event_trigger();
ERROR: permission denied to create event trigger "regress_event_trigger_noperms"
HINT: Must be superuser to create an event trigger.
reset role;
-- test enabling and disabling
alter event trigger regress_event_trigger disable;
-- fires _trigger2 and _trigger_end should fire, but not _trigger
create table event_trigger_fire1 (a int);
NOTICE: test_event_trigger: ddl_command_start CREATE TABLE
NOTICE: test_event_trigger: ddl_command_end CREATE TABLE
alter event trigger regress_event_trigger enable;
set session_replication_role = replica;
-- fires nothing
create table event_trigger_fire2 (a int);
alter event trigger regress_event_trigger enable replica;
-- fires only _trigger
create table event_trigger_fire3 (a int);
NOTICE: test_event_trigger: ddl_command_start CREATE TABLE
alter event trigger regress_event_trigger enable always;
-- fires only _trigger
create table event_trigger_fire4 (a int);
NOTICE: test_event_trigger: ddl_command_start CREATE TABLE
reset session_replication_role;
-- fires all three
create table event_trigger_fire5 (a int);
NOTICE: test_event_trigger: ddl_command_start CREATE TABLE
NOTICE: test_event_trigger: ddl_command_start CREATE TABLE
NOTICE: test_event_trigger: ddl_command_end CREATE TABLE
-- non-top-level command
create function f1() returns int
language plpgsql
as $$
begin
create table event_trigger_fire6 (a int);
return 0;
end $$;
NOTICE: test_event_trigger: ddl_command_start CREATE FUNCTION
NOTICE: test_event_trigger: ddl_command_start CREATE FUNCTION
NOTICE: test_event_trigger: ddl_command_end CREATE FUNCTION
select f1();
NOTICE: test_event_trigger: ddl_command_start CREATE TABLE
NOTICE: test_event_trigger: ddl_command_start CREATE TABLE
NOTICE: test_event_trigger: ddl_command_end CREATE TABLE
f1
----
0
(1 row)
-- non-top-level command
create procedure p1()
language plpgsql
as $$
begin
create table event_trigger_fire7 (a int);
end $$;
NOTICE: test_event_trigger: ddl_command_start CREATE PROCEDURE
NOTICE: test_event_trigger: ddl_command_end CREATE PROCEDURE
call p1();
NOTICE: test_event_trigger: ddl_command_start CREATE TABLE
NOTICE: test_event_trigger: ddl_command_start CREATE TABLE
NOTICE: test_event_trigger: ddl_command_end CREATE TABLE
-- clean up
alter event trigger regress_event_trigger disable;
drop table event_trigger_fire2, event_trigger_fire3, event_trigger_fire4, event_trigger_fire5, event_trigger_fire6, event_trigger_fire7;
NOTICE: test_event_trigger: ddl_command_end DROP TABLE
drop routine f1(), p1();
NOTICE: test_event_trigger: ddl_command_end DROP ROUTINE
-- regress_event_trigger_end should fire on these commands
grant all on table event_trigger_fire1 to public;
NOTICE: test_event_trigger: ddl_command_end GRANT
comment on table event_trigger_fire1 is 'here is a comment';
NOTICE: test_event_trigger: ddl_command_end COMMENT
revoke all on table event_trigger_fire1 from public;
NOTICE: test_event_trigger: ddl_command_end REVOKE
drop table event_trigger_fire1;
NOTICE: test_event_trigger: ddl_command_end DROP TABLE
create foreign data wrapper useless;
NOTICE: test_event_trigger: ddl_command_end CREATE FOREIGN DATA WRAPPER
create server useless_server foreign data wrapper useless;
NOTICE: test_event_trigger: ddl_command_end CREATE SERVER
create user mapping for regress_evt_user server useless_server;
NOTICE: test_event_trigger: ddl_command_end CREATE USER MAPPING
alter default privileges for role regress_evt_user
revoke delete on tables from regress_evt_user;
NOTICE: test_event_trigger: ddl_command_end ALTER DEFAULT PRIVILEGES
-- alter owner to non-superuser should fail
alter event trigger regress_event_trigger owner to regress_evt_user;
ERROR: permission denied to change owner of event trigger "regress_event_trigger"
HINT: The owner of an event trigger must be a superuser.
-- alter owner to superuser should work
alter role regress_evt_user superuser;
alter event trigger regress_event_trigger owner to regress_evt_user;
-- should fail, name collision
alter event trigger regress_event_trigger rename to regress_event_trigger2;
ERROR: event trigger "regress_event_trigger2" already exists
-- OK
alter event trigger regress_event_trigger rename to regress_event_trigger3;
-- should fail, doesn't exist any more
drop event trigger regress_event_trigger;
ERROR: event trigger "regress_event_trigger" does not exist
-- should fail, regress_evt_user owns some objects
drop role regress_evt_user;
ERROR: role "regress_evt_user" cannot be dropped because some objects depend on it
DETAIL: owner of event trigger regress_event_trigger3
owner of user mapping for regress_evt_user on server useless_server
owner of default privileges on new relations belonging to role regress_evt_user
-- cleanup before next test
-- these are all OK; the second one should emit a NOTICE
drop event trigger if exists regress_event_trigger2;
drop event trigger if exists regress_event_trigger2;
NOTICE: event trigger "regress_event_trigger2" does not exist, skipping
drop event trigger regress_event_trigger3;
drop event trigger regress_event_trigger_end;
-- test support for dropped objects
CREATE SCHEMA schema_one authorization regress_evt_user;
CREATE SCHEMA schema_two authorization regress_evt_user;
CREATE SCHEMA audit_tbls authorization regress_evt_user;
CREATE TEMP TABLE a_temp_tbl ();
SET SESSION AUTHORIZATION regress_evt_user;
CREATE TABLE schema_one.table_one(a int);
CREATE TABLE schema_one."table two"(a int);
CREATE TABLE schema_one.table_three(a int);
CREATE TABLE audit_tbls.schema_one_table_two(the_value text);
CREATE TABLE schema_two.table_two(a int);
CREATE TABLE schema_two.table_three(a int, b text);
CREATE TABLE audit_tbls.schema_two_table_three(the_value text);
CREATE OR REPLACE FUNCTION schema_two.add(int, int) RETURNS int LANGUAGE plpgsql
CALLED ON NULL INPUT
AS $$ BEGIN RETURN coalesce($1,0) + coalesce($2,0); END; $$;
CREATE AGGREGATE schema_two.newton
(BASETYPE = int, SFUNC = schema_two.add, STYPE = int);
RESET SESSION AUTHORIZATION;
CREATE TABLE undroppable_objs (
object_type text,
object_identity text
);
INSERT INTO undroppable_objs VALUES
('table', 'schema_one.table_three'),
('table', 'audit_tbls.schema_two_table_three');
CREATE TABLE dropped_objects (
type text,
schema text,
object text
);
-- This tests errors raised within event triggers; the one in audit_tbls
-- uses 2nd-level recursive invocation via test_evtrig_dropped_objects().
CREATE OR REPLACE FUNCTION undroppable() RETURNS event_trigger
LANGUAGE plpgsql AS $$
DECLARE
obj record;
BEGIN
PERFORM 1 FROM pg_tables WHERE tablename = 'undroppable_objs';
IF NOT FOUND THEN
RAISE NOTICE 'table undroppable_objs not found, skipping';
RETURN;
END IF;
FOR obj IN
SELECT * FROM pg_event_trigger_dropped_objects() JOIN
undroppable_objs USING (object_type, object_identity)
LOOP
RAISE EXCEPTION 'object % of type % cannot be dropped',
obj.object_identity, obj.object_type;
END LOOP;
END;
$$;
CREATE EVENT TRIGGER undroppable ON sql_drop
EXECUTE PROCEDURE undroppable();
CREATE OR REPLACE FUNCTION test_evtrig_dropped_objects() RETURNS event_trigger
LANGUAGE plpgsql AS $$
DECLARE
obj record;
BEGIN
FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
LOOP
IF obj.object_type = 'table' THEN
EXECUTE format('DROP TABLE IF EXISTS audit_tbls.%I',
format('%s_%s', obj.schema_name, obj.object_name));
END IF;
INSERT INTO dropped_objects
(type, schema, object) VALUES
(obj.object_type, obj.schema_name, obj.object_identity);
END LOOP;
END
$$;
CREATE EVENT TRIGGER regress_event_trigger_drop_objects ON sql_drop
WHEN TAG IN ('drop table', 'drop function', 'drop view',
'drop owned', 'drop schema', 'alter table')
EXECUTE PROCEDURE test_evtrig_dropped_objects();
ALTER TABLE schema_one.table_one DROP COLUMN a;
DROP SCHEMA schema_one, schema_two CASCADE;
NOTICE: drop cascades to 7 other objects
DETAIL: drop cascades to table schema_two.table_two
drop cascades to table schema_two.table_three
drop cascades to function schema_two.add(integer,integer)
drop cascades to function schema_two.newton(integer)
drop cascades to table schema_one.table_one
drop cascades to table schema_one."table two"
drop cascades to table schema_one.table_three
NOTICE: table "schema_two_table_two" does not exist, skipping
NOTICE: table "audit_tbls_schema_two_table_three" does not exist, skipping
ERROR: object audit_tbls.schema_two_table_three of type table cannot be dropped
CONTEXT: PL/pgSQL function undroppable() line 14 at RAISE
SQL statement "DROP TABLE IF EXISTS audit_tbls.schema_two_table_three"
PL/pgSQL function test_evtrig_dropped_objects() line 8 at EXECUTE
DELETE FROM undroppable_objs WHERE object_identity = 'audit_tbls.schema_two_table_three';
DROP SCHEMA schema_one, schema_two CASCADE;
NOTICE: drop cascades to 7 other objects
DETAIL: drop cascades to table schema_two.table_two
drop cascades to table schema_two.table_three
drop cascades to function schema_two.add(integer,integer)
drop cascades to function schema_two.newton(integer)
drop cascades to table schema_one.table_one
drop cascades to table schema_one."table two"
drop cascades to table schema_one.table_three
NOTICE: table "schema_two_table_two" does not exist, skipping
NOTICE: table "audit_tbls_schema_two_table_three" does not exist, skipping
NOTICE: table "schema_one_table_one" does not exist, skipping
NOTICE: table "schema_one_table two" does not exist, skipping
NOTICE: table "schema_one_table_three" does not exist, skipping
ERROR: object schema_one.table_three of type table cannot be dropped
CONTEXT: PL/pgSQL function undroppable() line 14 at RAISE
DELETE FROM undroppable_objs WHERE object_identity = 'schema_one.table_three';
DROP SCHEMA schema_one, schema_two CASCADE;
NOTICE: drop cascades to 7 other objects
DETAIL: drop cascades to table schema_two.table_two
drop cascades to table schema_two.table_three
drop cascades to function schema_two.add(integer,integer)
drop cascades to function schema_two.newton(integer)
drop cascades to table schema_one.table_one
drop cascades to table schema_one."table two"
drop cascades to table schema_one.table_three
NOTICE: table "schema_two_table_two" does not exist, skipping
NOTICE: table "audit_tbls_schema_two_table_three" does not exist, skipping
NOTICE: table "schema_one_table_one" does not exist, skipping
NOTICE: table "schema_one_table two" does not exist, skipping
NOTICE: table "schema_one_table_three" does not exist, skipping
SELECT * FROM dropped_objects WHERE schema IS NULL OR schema <> 'pg_toast';
type | schema | object
--------------+------------+-------------------------------------
table column | schema_one | schema_one.table_one.a
schema | | schema_two
table | schema_two | schema_two.table_two
type | schema_two | schema_two.table_two
type | schema_two | schema_two.table_two[]
table | audit_tbls | audit_tbls.schema_two_table_three
type | audit_tbls | audit_tbls.schema_two_table_three
type | audit_tbls | audit_tbls.schema_two_table_three[]
table | schema_two | schema_two.table_three
type | schema_two | schema_two.table_three
type | schema_two | schema_two.table_three[]
function | schema_two | schema_two.add(integer,integer)
aggregate | schema_two | schema_two.newton(integer)
schema | | schema_one
table | schema_one | schema_one.table_one
type | schema_one | schema_one.table_one
type | schema_one | schema_one.table_one[]
table | schema_one | schema_one."table two"
type | schema_one | schema_one."table two"
type | schema_one | schema_one."table two"[]
table | schema_one | schema_one.table_three
type | schema_one | schema_one.table_three
type | schema_one | schema_one.table_three[]
(23 rows)
DROP OWNED BY regress_evt_user;
NOTICE: schema "audit_tbls" does not exist, skipping
SELECT * FROM dropped_objects WHERE type = 'schema';
type | schema | object
--------+--------+------------
schema | | schema_two
schema | | schema_one
schema | | audit_tbls
(3 rows)
DROP ROLE regress_evt_user;
DROP EVENT TRIGGER regress_event_trigger_drop_objects;
DROP EVENT TRIGGER undroppable;
-- Event triggers on relations.
CREATE OR REPLACE FUNCTION event_trigger_report_dropped()
RETURNS event_trigger
LANGUAGE plpgsql
AS $$
DECLARE r record;
BEGIN
FOR r IN SELECT * from pg_event_trigger_dropped_objects()
LOOP
IF NOT r.normal AND NOT r.original THEN
CONTINUE;
END IF;
RAISE NOTICE 'NORMAL: orig=% normal=% istemp=% type=% identity=% name=% args=%',
r.original, r.normal, r.is_temporary, r.object_type,
r.object_identity, r.address_names, r.address_args;
END LOOP;
END; $$;
CREATE EVENT TRIGGER regress_event_trigger_report_dropped ON sql_drop
EXECUTE PROCEDURE event_trigger_report_dropped();
CREATE OR REPLACE FUNCTION event_trigger_report_end()
RETURNS event_trigger
LANGUAGE plpgsql
AS $$
DECLARE r RECORD;
BEGIN
FOR r IN SELECT * FROM pg_event_trigger_ddl_commands()
LOOP
RAISE NOTICE 'END: command_tag=% type=% identity=%',
r.command_tag, r.object_type, r.object_identity;
END LOOP;
END; $$;
CREATE EVENT TRIGGER regress_event_trigger_report_end ON ddl_command_end
EXECUTE PROCEDURE event_trigger_report_end();
CREATE SCHEMA evttrig
CREATE TABLE one (col_a SERIAL PRIMARY KEY, col_b text DEFAULT 'forty two', col_c SERIAL)
CREATE INDEX one_idx ON one (col_b)
CREATE TABLE two (col_c INTEGER CHECK (col_c > 0) REFERENCES one DEFAULT 42)
CREATE TABLE id (col_d int NOT NULL GENERATED ALWAYS AS IDENTITY);
NOTICE: END: command_tag=CREATE SCHEMA type=schema identity=evttrig
NOTICE: END: command_tag=CREATE SEQUENCE type=sequence identity=evttrig.one_col_a_seq
NOTICE: END: command_tag=CREATE SEQUENCE type=sequence identity=evttrig.one_col_c_seq
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.one
NOTICE: END: command_tag=CREATE INDEX type=index identity=evttrig.one_pkey
NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.one_col_a_seq
NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.one_col_c_seq
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.two
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.two
NOTICE: END: command_tag=CREATE SEQUENCE type=sequence identity=evttrig.id_col_d_seq
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.id
NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.id_col_d_seq
NOTICE: END: command_tag=CREATE INDEX type=index identity=evttrig.one_idx
-- Partitioned tables with a partitioned index
CREATE TABLE evttrig.parted (
id int PRIMARY KEY)
PARTITION BY RANGE (id);
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.parted
NOTICE: END: command_tag=CREATE INDEX type=index identity=evttrig.parted_pkey
CREATE TABLE evttrig.part_1_10 PARTITION OF evttrig.parted (id)
FOR VALUES FROM (1) TO (10);
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.part_1_10
CREATE TABLE evttrig.part_10_20 PARTITION OF evttrig.parted (id)
FOR VALUES FROM (10) TO (20) PARTITION BY RANGE (id);
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.part_10_20
CREATE TABLE evttrig.part_10_15 PARTITION OF evttrig.part_10_20 (id)
FOR VALUES FROM (10) TO (15);
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.part_10_15
CREATE TABLE evttrig.part_15_20 PARTITION OF evttrig.part_10_20 (id)
FOR VALUES FROM (15) TO (20);
NOTICE: END: command_tag=CREATE TABLE type=table identity=evttrig.part_15_20
ALTER TABLE evttrig.two DROP COLUMN col_c;
NOTICE: NORMAL: orig=t normal=f istemp=f type=table column identity=evttrig.two.col_c name={evttrig,two,col_c} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=table constraint identity=two_col_c_check on evttrig.two name={evttrig,two,two_col_c_check} args={}
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.two
ALTER TABLE evttrig.one ALTER COLUMN col_b DROP DEFAULT;
NOTICE: NORMAL: orig=t normal=f istemp=f type=default value identity=for evttrig.one.col_b name={evttrig,one,col_b} args={}
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.one
ALTER TABLE evttrig.one DROP CONSTRAINT one_pkey;
NOTICE: NORMAL: orig=t normal=f istemp=f type=table constraint identity=one_pkey on evttrig.one name={evttrig,one,one_pkey} args={}
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.one
ALTER TABLE evttrig.one DROP COLUMN col_c;
NOTICE: NORMAL: orig=t normal=f istemp=f type=table column identity=evttrig.one.col_c name={evttrig,one,col_c} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=default value identity=for evttrig.one.col_c name={evttrig,one,col_c} args={}
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.one
ALTER TABLE evttrig.id ALTER COLUMN col_d SET DATA TYPE bigint;
NOTICE: END: command_tag=ALTER SEQUENCE type=sequence identity=evttrig.id_col_d_seq
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.id
ALTER TABLE evttrig.id ALTER COLUMN col_d DROP IDENTITY,
ALTER COLUMN col_d SET DATA TYPE int;
NOTICE: END: command_tag=ALTER TABLE type=table identity=evttrig.id
DROP INDEX evttrig.one_idx;
NOTICE: NORMAL: orig=t normal=f istemp=f type=index identity=evttrig.one_idx name={evttrig,one_idx} args={}
DROP SCHEMA evttrig CASCADE;
NOTICE: drop cascades to 4 other objects
DETAIL: drop cascades to table evttrig.one
drop cascades to table evttrig.two
drop cascades to table evttrig.id
drop cascades to table evttrig.parted
NOTICE: NORMAL: orig=t normal=f istemp=f type=schema identity=evttrig name={evttrig} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.one name={evttrig,one} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=sequence identity=evttrig.one_col_a_seq name={evttrig,one_col_a_seq} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=default value identity=for evttrig.one.col_a name={evttrig,one,col_a} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.two name={evttrig,two} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.id name={evttrig,id} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.parted name={evttrig,parted} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_1_10 name={evttrig,part_1_10} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_10_20 name={evttrig,part_10_20} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_10_15 name={evttrig,part_10_15} args={}
NOTICE: NORMAL: orig=f normal=t istemp=f type=table identity=evttrig.part_15_20 name={evttrig,part_15_20} args={}
DROP TABLE a_temp_tbl;
NOTICE: NORMAL: orig=t normal=f istemp=t type=table identity=pg_temp.a_temp_tbl name={pg_temp,a_temp_tbl} args={}
-- CREATE OPERATOR CLASS without FAMILY clause should report
-- both CREATE OPERATOR FAMILY and CREATE OPERATOR CLASS
CREATE OPERATOR CLASS evttrigopclass FOR TYPE int USING btree AS STORAGE int;
NOTICE: END: command_tag=CREATE OPERATOR FAMILY type=operator family identity=public.evttrigopclass USING btree
NOTICE: END: command_tag=CREATE OPERATOR CLASS type=operator class identity=public.evttrigopclass USING btree
DROP EVENT TRIGGER regress_event_trigger_report_dropped;
DROP EVENT TRIGGER regress_event_trigger_report_end;
-- only allowed from within an event trigger function, should fail
select pg_event_trigger_table_rewrite_oid();
ERROR: pg_event_trigger_table_rewrite_oid() can only be called in a table_rewrite event trigger function
-- test Table Rewrite Event Trigger
CREATE OR REPLACE FUNCTION test_evtrig_no_rewrite() RETURNS event_trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE EXCEPTION 'rewrites not allowed';
END;
$$;
create event trigger no_rewrite_allowed on table_rewrite
execute procedure test_evtrig_no_rewrite();
create table rewriteme (id serial primary key, foo float, bar timestamptz);
insert into rewriteme
select x * 1.001 from generate_series(1, 500) as t(x);
alter table rewriteme alter column foo type numeric;
ERROR: rewrites not allowed
CONTEXT: PL/pgSQL function test_evtrig_no_rewrite() line 3 at RAISE
alter table rewriteme add column baz int default 0;
-- test with more than one reason to rewrite a single table
CREATE OR REPLACE FUNCTION test_evtrig_no_rewrite() RETURNS event_trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE NOTICE 'Table ''%'' is being rewritten (reason = %)',
pg_event_trigger_table_rewrite_oid()::regclass,
pg_event_trigger_table_rewrite_reason();
END;
$$;
alter table rewriteme
add column onemore int default 0,
add column another int default -1,
alter column foo type numeric(10,4);
NOTICE: Table 'rewriteme' is being rewritten (reason = 4)
-- matview rewrite when changing access method
CREATE MATERIALIZED VIEW heapmv USING heap AS SELECT 1 AS a;
ALTER MATERIALIZED VIEW heapmv SET ACCESS METHOD heap2;
NOTICE: Table 'heapmv' is being rewritten (reason = 8)
DROP MATERIALIZED VIEW heapmv;
-- shouldn't trigger a table_rewrite event
alter table rewriteme alter column foo type numeric(12,4);
begin;
set timezone to 'UTC';
alter table rewriteme alter column bar type timestamp;
set timezone to '0';
alter table rewriteme alter column bar type timestamptz;
set timezone to 'Europe/London';
alter table rewriteme alter column bar type timestamp; -- does rewrite
NOTICE: Table 'rewriteme' is being rewritten (reason = 4)
rollback;
-- typed tables are rewritten when their type changes. Don't emit table
-- name, because firing order is not stable.
CREATE OR REPLACE FUNCTION test_evtrig_no_rewrite() RETURNS event_trigger
LANGUAGE plpgsql AS $$
BEGIN
RAISE NOTICE 'Table is being rewritten (reason = %)',
pg_event_trigger_table_rewrite_reason();
END;
$$;
create type rewritetype as (a int);
create table rewritemetoo1 of rewritetype;
create table rewritemetoo2 of rewritetype;
alter type rewritetype alter attribute a type text cascade;
NOTICE: Table is being rewritten (reason = 4)
NOTICE: Table is being rewritten (reason = 4)
-- but this doesn't work
create table rewritemetoo3 (a rewritetype);
alter type rewritetype alter attribute a type varchar cascade;
ERROR: cannot alter type "rewritetype" because column "rewritemetoo3.a" uses it
drop table rewriteme;
drop event trigger no_rewrite_allowed;
drop function test_evtrig_no_rewrite();
-- Tests for REINDEX
CREATE OR REPLACE FUNCTION reindex_start_command()
RETURNS event_trigger AS $$
BEGIN
RAISE NOTICE 'REINDEX START: % %', tg_event, tg_tag;
END;
$$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER regress_reindex_start ON ddl_command_start
WHEN TAG IN ('REINDEX')
EXECUTE PROCEDURE reindex_start_command();
CREATE FUNCTION reindex_end_command()
RETURNS event_trigger AS $$
DECLARE
obj record;
BEGIN
FOR obj IN SELECT * FROM pg_event_trigger_ddl_commands()
LOOP
RAISE NOTICE 'REINDEX END: command_tag=% type=% identity=%',
obj.command_tag, obj.object_type, obj.object_identity;
END LOOP;
END;
$$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER regress_reindex_end ON ddl_command_end
WHEN TAG IN ('REINDEX')
EXECUTE PROCEDURE reindex_end_command();
-- Extra event to force the use of a snapshot.
CREATE FUNCTION reindex_end_command_snap() RETURNS EVENT_TRIGGER
AS $$ BEGIN PERFORM 1; END $$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER regress_reindex_end_snap ON ddl_command_end
EXECUTE FUNCTION reindex_end_command_snap();
-- With simple relation
CREATE TABLE concur_reindex_tab (c1 int);
CREATE INDEX concur_reindex_ind ON concur_reindex_tab (c1);
-- Both start and end triggers enabled.
REINDEX INDEX concur_reindex_ind;
NOTICE: REINDEX START: ddl_command_start REINDEX
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind
REINDEX TABLE concur_reindex_tab;
NOTICE: REINDEX START: ddl_command_start REINDEX
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind
REINDEX INDEX CONCURRENTLY concur_reindex_ind;
NOTICE: REINDEX START: ddl_command_start REINDEX
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind
REINDEX TABLE CONCURRENTLY concur_reindex_tab;
NOTICE: REINDEX START: ddl_command_start REINDEX
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind
-- with start trigger disabled.
ALTER EVENT TRIGGER regress_reindex_start DISABLE;
REINDEX INDEX concur_reindex_ind;
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind
REINDEX INDEX CONCURRENTLY concur_reindex_ind;
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_ind
-- without an index
DROP INDEX concur_reindex_ind;
REINDEX TABLE concur_reindex_tab;
NOTICE: table "concur_reindex_tab" has no indexes to reindex
REINDEX TABLE CONCURRENTLY concur_reindex_tab;
NOTICE: table "concur_reindex_tab" has no indexes that can be reindexed concurrently
-- With a Schema
CREATE SCHEMA concur_reindex_schema;
-- No indexes
REINDEX SCHEMA concur_reindex_schema;
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema;
CREATE TABLE concur_reindex_schema.tab (a int);
CREATE INDEX ind ON concur_reindex_schema.tab (a);
-- One index reported
REINDEX SCHEMA concur_reindex_schema;
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=concur_reindex_schema.ind
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema;
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=concur_reindex_schema.ind
-- One table on schema but no indexes
DROP INDEX concur_reindex_schema.ind;
REINDEX SCHEMA concur_reindex_schema;
REINDEX SCHEMA CONCURRENTLY concur_reindex_schema;
DROP SCHEMA concur_reindex_schema CASCADE;
NOTICE: drop cascades to table concur_reindex_schema.tab
-- With a partitioned table, and nothing else.
CREATE TABLE concur_reindex_part (id int) PARTITION BY RANGE (id);
REINDEX TABLE concur_reindex_part;
REINDEX TABLE CONCURRENTLY concur_reindex_part;
-- Partition that would be reindexed, still nothing.
CREATE TABLE concur_reindex_child PARTITION OF concur_reindex_part
FOR VALUES FROM (0) TO (10);
REINDEX TABLE concur_reindex_part;
REINDEX TABLE CONCURRENTLY concur_reindex_part;
-- Now add some indexes.
CREATE INDEX concur_reindex_partidx ON concur_reindex_part (id);
REINDEX INDEX concur_reindex_partidx;
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_child_id_idx
REINDEX INDEX CONCURRENTLY concur_reindex_partidx;
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_child_id_idx
REINDEX TABLE concur_reindex_part;
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_child_id_idx
REINDEX TABLE CONCURRENTLY concur_reindex_part;
NOTICE: REINDEX END: command_tag=REINDEX type=index identity=public.concur_reindex_child_id_idx
DROP TABLE concur_reindex_part;
-- Clean up
DROP EVENT TRIGGER regress_reindex_start;
DROP EVENT TRIGGER regress_reindex_end;
DROP EVENT TRIGGER regress_reindex_end_snap;
DROP FUNCTION reindex_end_command();
DROP FUNCTION reindex_end_command_snap();
DROP FUNCTION reindex_start_command();
DROP TABLE concur_reindex_tab;
-- test Row Security Event Trigger
RESET SESSION AUTHORIZATION;
CREATE TABLE event_trigger_test (a integer, b text);
CREATE OR REPLACE FUNCTION start_command()
RETURNS event_trigger AS $$
BEGIN
RAISE NOTICE '% - ddl_command_start', tg_tag;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION end_command()
RETURNS event_trigger AS $$
BEGIN
RAISE NOTICE '% - ddl_command_end', tg_tag;
END;
$$ LANGUAGE plpgsql;
CREATE OR REPLACE FUNCTION drop_sql_command()
RETURNS event_trigger AS $$
BEGIN
RAISE NOTICE '% - sql_drop', tg_tag;
END;
$$ LANGUAGE plpgsql;
CREATE EVENT TRIGGER start_rls_command ON ddl_command_start
WHEN TAG IN ('CREATE POLICY', 'ALTER POLICY', 'DROP POLICY') EXECUTE PROCEDURE start_command();
CREATE EVENT TRIGGER end_rls_command ON ddl_command_end
WHEN TAG IN ('CREATE POLICY', 'ALTER POLICY', 'DROP POLICY') EXECUTE PROCEDURE end_command();
CREATE EVENT TRIGGER sql_drop_command ON sql_drop
WHEN TAG IN ('DROP POLICY') EXECUTE PROCEDURE drop_sql_command();
CREATE POLICY p1 ON event_trigger_test USING (FALSE);
NOTICE: CREATE POLICY - ddl_command_start
NOTICE: CREATE POLICY - ddl_command_end
ALTER POLICY p1 ON event_trigger_test USING (TRUE);
NOTICE: ALTER POLICY - ddl_command_start
NOTICE: ALTER POLICY - ddl_command_end
ALTER POLICY p1 ON event_trigger_test RENAME TO p2;
NOTICE: ALTER POLICY - ddl_command_start
NOTICE: ALTER POLICY - ddl_command_end
DROP POLICY p2 ON event_trigger_test;
NOTICE: DROP POLICY - ddl_command_start
NOTICE: DROP POLICY - sql_drop
NOTICE: DROP POLICY - ddl_command_end
-- Check the object addresses of all the event triggers.
SELECT
e.evtname,
pg_describe_object('pg_event_trigger'::regclass, e.oid, 0) as descr,
b.type, b.object_names, b.object_args,
pg_identify_object(a.classid, a.objid, a.objsubid) as ident
FROM pg_event_trigger as e,
LATERAL pg_identify_object_as_address('pg_event_trigger'::regclass, e.oid, 0) as b,
LATERAL pg_get_object_address(b.type, b.object_names, b.object_args) as a
ORDER BY e.evtname;
evtname | descr | type | object_names | object_args | ident
-------------------------------+---------------------------------------------+---------------+---------------------------------+-------------+--------------------------------------------------------------------------------
end_rls_command | event trigger end_rls_command | event trigger | {end_rls_command} | {} | ("event trigger",,end_rls_command,end_rls_command)
pg_tde_trigger_create_index | event trigger pg_tde_trigger_create_index | event trigger | {pg_tde_trigger_create_index} | {} | ("event trigger",,pg_tde_trigger_create_index,pg_tde_trigger_create_index)
pg_tde_trigger_create_index_2 | event trigger pg_tde_trigger_create_index_2 | event trigger | {pg_tde_trigger_create_index_2} | {} | ("event trigger",,pg_tde_trigger_create_index_2,pg_tde_trigger_create_index_2)
sql_drop_command | event trigger sql_drop_command | event trigger | {sql_drop_command} | {} | ("event trigger",,sql_drop_command,sql_drop_command)
start_rls_command | event trigger start_rls_command | event trigger | {start_rls_command} | {} | ("event trigger",,start_rls_command,start_rls_command)
(5 rows)
DROP EVENT TRIGGER start_rls_command;
DROP EVENT TRIGGER end_rls_command;
DROP EVENT TRIGGER sql_drop_command;
-- Check the GUC for disabling event triggers
CREATE FUNCTION test_event_trigger_guc() RETURNS event_trigger
LANGUAGE plpgsql AS $$
DECLARE
obj record;
BEGIN
FOR obj IN SELECT * FROM pg_event_trigger_dropped_objects()
LOOP
RAISE NOTICE '% dropped %', tg_tag, obj.object_type;
END LOOP;
END;
$$;
CREATE EVENT TRIGGER test_event_trigger_guc
ON sql_drop
WHEN TAG IN ('DROP POLICY') EXECUTE FUNCTION test_event_trigger_guc();
SET event_triggers = 'on';
CREATE POLICY pguc ON event_trigger_test USING (FALSE);
DROP POLICY pguc ON event_trigger_test;
NOTICE: DROP POLICY dropped policy
CREATE POLICY pguc ON event_trigger_test USING (FALSE);
SET event_triggers = 'off';
DROP POLICY pguc ON event_trigger_test;

File diff suppressed because it is too large Load Diff

@ -103,6 +103,7 @@ char *expecteddir = ".";
char *bindir = PGBINDIR;
char *launcher = NULL;
static _stringlist *loadextension = NULL;
char *exec_sql = NULL;
static int max_connections = 0;
static int max_concurrent_tests = 0;
static char *encoding = NULL;
@ -1983,6 +1984,25 @@ create_database(const char *dbname)
*/
for (sl = loadextension; sl != NULL; sl = sl->next)
psql_command(dbname, "CREATE EXTENSION IF NOT EXISTS \"%s\"", sl->str);
/*
* Percona extension
* Execute any additional sql commands provided by caller
*/
if (exec_sql)
{
FILE *sql_file;
char line_buf[2048];
sql_file = fopen(exec_sql, "r");
if (sql_file == NULL)
{
bail("could not open \"%s\" to read extra setup file: %s",
exec_sql, strerror(errno));
}
while (fgets(line_buf, sizeof(line_buf), sql_file) != NULL)
psql_command(dbname,"%s",line_buf);
fclose(sql_file);
}
}
static void
@ -2032,6 +2052,8 @@ help(void)
printf(_(" --launcher=CMD use CMD as launcher of psql\n"));
printf(_(" --load-extension=EXT load the named extension before running the\n"));
printf(_(" tests; can appear multiple times\n"));
printf(_(" --extra-setup=FILE file containing optional SQL commands to run before running the\n"));
printf(_(" tests;\n"));
printf(_(" --max-connections=N maximum number of concurrent connections\n"));
printf(_(" (default is 0, meaning unlimited)\n"));
printf(_(" --max-concurrent-tests=N maximum number of concurrent tests in schedule\n"));
@ -2091,6 +2113,7 @@ regression_main(int argc, char *argv[],
{"config-auth", required_argument, NULL, 24},
{"max-concurrent-tests", required_argument, NULL, 25},
{"expecteddir", required_argument, NULL, 26},
{"extra-setup", required_argument, NULL, 27},
{NULL, 0, NULL, 0}
};
@ -2219,6 +2242,9 @@ regression_main(int argc, char *argv[],
case 26:
expecteddir = pg_strdup(optarg);
break;
case 27:
exec_sql = pg_strdup(optarg);
break;
default:
/* getopt_long already emitted a complaint */
pg_log_error_hint("Try \"%s --help\" for more information.",

Loading…
Cancel
Save