diff --git a/contrib/dolphin/expected/case_sensitive_test/alter_table.out b/contrib/dolphin/expected/case_sensitive_test/alter_table.out new file mode 100644 index 0000000000000000000000000000000000000000..acf8ba9b2837f7b0bd496052a9e1413c7b509e58 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/alter_table.out @@ -0,0 +1,474 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +--FOR BLACKLIST FEATURE: REFERENCES/INHERITS/WITH OIDS/RULE/CREATE TYPE/DOMAIN is not supported. +-- +-- +-- ALTER_TABLE +-- add attribute +-- +CREATE TABLE Tmp (initial int4); +COMMENT ON TABLE tmp_wrong IS 'table comment'; +ERROR: relation "tmp_wrong" does not exist +COMMENT ON TABLE Tmp IS 'table comment'; +COMMENT ON TABLE Tmp IS NULL; +ALTER TABLE Tmp ADD COLUMN xmin integer; -- fails +ERROR: column name "xmin" conflicts with a system column name +ALTER TABLE Tmp ADD COLUMN a int4 default 3; +ALTER TABLE Tmp ADD COLUMN b name; +ALTER TABLE Tmp ADD COLUMN c text; +ALTER TABLE Tmp ADD COLUMN d float8; +ALTER TABLE Tmp ADD COLUMN e float4; +ALTER TABLE Tmp ADD COLUMN f int2; +ALTER TABLE Tmp ADD COLUMN g polygon; +ALTER TABLE Tmp ADD COLUMN h abstime; +ALTER TABLE Tmp ADD COLUMN i char; +ALTER TABLE Tmp ADD COLUMN j abstime[]; +ALTER TABLE Tmp ADD COLUMN k int4; +ALTER TABLE Tmp ADD COLUMN l tid; +ALTER TABLE Tmp ADD COLUMN m xid; +ALTER TABLE Tmp ADD COLUMN n oidvector; +--ALTER TABLE Tmp ADD COLUMN o lock; +ALTER TABLE Tmp ADD COLUMN p smgr; +ALTER TABLE Tmp ADD COLUMN q point; +ALTER TABLE Tmp ADD COLUMN r lseg; +ALTER TABLE Tmp ADD COLUMN s path; +ALTER TABLE Tmp ADD COLUMN t box; +ALTER TABLE Tmp ADD COLUMN u tinterval; +ALTER TABLE Tmp ADD COLUMN v timestamp; +ALTER TABLE Tmp ADD COLUMN w interval; +ALTER TABLE Tmp ADD COLUMN x float8[]; +ALTER TABLE Tmp ADD COLUMN y float4[]; +ALTER TABLE Tmp ADD COLUMN z int2[]; +INSERT INTO Tmp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, p, q, r, s, t, u, + v, w, x, y, z) + VALUES (4, 'name', 'text', 4.1, 4.1, 2, '(4.1,4.1,3.1,3.1)', + 'Mon May 1 00:30:30 1995', 'c', '{Mon May 1 00:30:30 1995, Monday Aug 24 14:43:07 1992, epoch}', + 314159, '(1,1)', '512', + '1 2 3 4 5 6 7 8', 'magnetic disk', '(1.1,1.1)', '(4.1,4.1,3.1,3.1)', + '(0,2,4.1,4.1,3.1,3.1)', '(4.1,4.1,3.1,3.1)', '["epoch" "infinity"]', + 'epoch', '01:00:10', '{1.0,2.0,3.0,4.0}', '{1.0,2.0,3.0,4.0}', '{1,2,3,4}'); +SELECT * FROM Tmp; + initial | a | b | c | d | e | f | g | h | i | j | k | l | m | n | p | q | r | s | t | u | v | w | x | y | z +---------+---+------+------+-----+-----+---+-----------------------+------------------------------+---+------------------------------------------------------------------------------------------------+--------+-------+-----+-----------------+---------------+-----------+-----------------------+-----------------------------+---------------------+---------------------------------------------+------------------------------+------------------+-----------+-----------+----------- + | 4 | name | text | 4.1 | 4.1 | 2 | ((4.1,4.1),(3.1,3.1)) | Mon May 01 00:30:30 1995 PDT | c | {"Mon May 01 00:30:30 1995 PDT","Mon Aug 24 14:43:07 1992 PDT","Wed Dec 31 16:00:00 1969 PST"} | 314159 | (1,1) | 512 | 1 2 3 4 5 6 7 8 | magnetic disk | (1.1,1.1) | [(4.1,4.1),(3.1,3.1)] | ((0,2),(4.1,4.1),(3.1,3.1)) | (4.1,4.1),(3.1,3.1) | ["Wed Dec 31 16:00:00 1969 PST" "infinity"] | Wed Dec 31 16:00:00 1969 PST | @ 1 hour 10 secs | {1,2,3,4} | {1,2,3,4} | {1,2,3,4} +(1 row) + +DROP TABLE Tmp; +-- the wolf bug - schema mods caused inconsistent row descriptors +CREATE TABLE Tmp ( + initial int4 +); +ALTER TABLE Tmp ADD COLUMN a int4; +ALTER TABLE Tmp ADD COLUMN b name; +ALTER TABLE Tmp ADD COLUMN c text; +ALTER TABLE Tmp ADD COLUMN d float8; +ALTER TABLE Tmp ADD COLUMN e float4; +ALTER TABLE Tmp ADD COLUMN f int2; +ALTER TABLE Tmp ADD COLUMN g polygon; +ALTER TABLE Tmp ADD COLUMN h abstime; +ALTER TABLE Tmp ADD COLUMN i char; +ALTER TABLE Tmp ADD COLUMN j abstime[]; +ALTER TABLE Tmp ADD COLUMN k int4; +ALTER TABLE Tmp ADD COLUMN l tid; +ALTER TABLE Tmp ADD COLUMN m xid; +ALTER TABLE Tmp ADD COLUMN n oidvector; +--ALTER TABLE Tmp ADD COLUMN o lock; +ALTER TABLE Tmp ADD COLUMN p smgr; +ALTER TABLE Tmp ADD COLUMN q point; +ALTER TABLE Tmp ADD COLUMN r lseg; +ALTER TABLE Tmp ADD COLUMN s path; +ALTER TABLE Tmp ADD COLUMN t box; +ALTER TABLE Tmp ADD COLUMN u tinterval; +ALTER TABLE Tmp ADD COLUMN v timestamp; +ALTER TABLE Tmp ADD COLUMN w interval; +ALTER TABLE Tmp ADD COLUMN x float8[]; +ALTER TABLE Tmp ADD COLUMN y float4[]; +ALTER TABLE Tmp ADD COLUMN z int2[]; +INSERT INTO Tmp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, p, q, r, s, t, u, + v, w, x, y, z) + VALUES (4, 'name', 'text', 4.1, 4.1, 2, '(4.1,4.1,3.1,3.1)', + 'Mon May 1 00:30:30 1995', 'c', '{Mon May 1 00:30:30 1995, Monday Aug 24 14:43:07 1992, epoch}', + 314159, '(1,1)', '512', + '1 2 3 4 5 6 7 8', 'magnetic disk', '(1.1,1.1)', '(4.1,4.1,3.1,3.1)', + '(0,2,4.1,4.1,3.1,3.1)', '(4.1,4.1,3.1,3.1)', '["epoch" "infinity"]', + 'epoch', '01:00:10', '{1.0,2.0,3.0,4.0}', '{1.0,2.0,3.0,4.0}', '{1,2,3,4}'); +SELECT * FROM Tmp; + initial | a | b | c | d | e | f | g | h | i | j | k | l | m | n | p | q | r | s | t | u | v | w | x | y | z +---------+---+------+------+-----+-----+---+-----------------------+------------------------------+---+------------------------------------------------------------------------------------------------+--------+-------+-----+-----------------+---------------+-----------+-----------------------+-----------------------------+---------------------+---------------------------------------------+------------------------------+------------------+-----------+-----------+----------- + | 4 | name | text | 4.1 | 4.1 | 2 | ((4.1,4.1),(3.1,3.1)) | Mon May 01 00:30:30 1995 PDT | c | {"Mon May 01 00:30:30 1995 PDT","Mon Aug 24 14:43:07 1992 PDT","Wed Dec 31 16:00:00 1969 PST"} | 314159 | (1,1) | 512 | 1 2 3 4 5 6 7 8 | magnetic disk | (1.1,1.1) | [(4.1,4.1),(3.1,3.1)] | ((0,2),(4.1,4.1),(3.1,3.1)) | (4.1,4.1),(3.1,3.1) | ["Wed Dec 31 16:00:00 1969 PST" "infinity"] | Wed Dec 31 16:00:00 1969 PST | @ 1 hour 10 secs | {1,2,3,4} | {1,2,3,4} | {1,2,3,4} +(1 row) + +DROP TABLE Tmp; +-- +-- rename - check on both non-temp and temp tables +-- +CREATE TABLE Tmp (regtable int); +-- Enforce use of COMMIT instead of 2PC for temporary objects +\set VERBOSITY verbose +-- CREATE TEMP TABLE Tmp (tmptable int); +ALTER TABLE Tmp RENAME TO Tmp_new; +-- SELECT * FROM Tmp; +-- SELECT * FROM Tmp_new; +-- ALTER TABLE Tmp RENAME TO Tmp_new2; +SELECT * FROM Tmp; -- should fail +ERROR: +--?GAUSS.*: relation "Tmp" does not exist on datanode1 +SQLSTATE: 42P01 +LINE 1: SELECT * FROM Tmp; + ^ +--?.* +SELECT *, FROM Tmp; -- should fail +ERROR: syntax error at or near "FROM" +SQLSTATE: 42601 +LINE 1: SELECT *, FROM Tmp; + ^ +--?.* +SELECT * FROM Tmp_new; + regtable +---------- +(0 rows) + +-- SELECT * FROM Tmp_new2; +DROP TABLE Tmp_new; +-- DROP TABLE Tmp_new2; +CREATE TABLE Tmp (ch1 character(1)); +insert into Tmp values ('asdv'); +ERROR: value too long for type character(1) +SQLSTATE: 22001 +CONTEXT: referenced column: ch1 +--?.* +DROP TABLE Tmp; +\set VERBOSITY default +-- ALTER TABLE ... RENAME on non-table relations +-- renaming indexes (FIXME: this should probably test the index's functionality) +ALTER INDEX IF EXISTS __onek_unique1 RENAME TO tmp_onek_unique1; +NOTICE: relation "__onek_unique1" does not exist, skipping +ALTER INDEX IF EXISTS __tmp_onek_unique1 RENAME TO onek_unique1; +NOTICE: relation "__tmp_onek_unique1" does not exist, skipping +ALTER INDEX onek_unique1 RENAME TO tmp_onek_unique1; +ALTER INDEX tmp_onek_unique1 RENAME TO onek_unique1; +-- renaming views +CREATE VIEW tmp_view (unique1) AS SELECT unique1 FROM Tenk1; +ALTER TABLE tmp_view RENAME TO tmp_view_new; +-- hack to ensure we get an indexscan here +ANALYZE Tenk1; +set enable_seqscan to off; +set enable_bitmapscan to off; +-- 5 values, sorted +SELECT unique1 FROM Tenk1 WHERE unique1 < 5 ORDER BY unique1; + unique1 +--------- +(0 rows) + +reset enable_seqscan; +reset enable_bitmapscan; +DROP VIEW tmp_view_new; +-- toast-like relation name +alter table Stud_Emp rename to pg_toast_stud_emp; +alter table pg_toast_stud_emp rename to Stud_Emp; +-- renaming index should rename constraint as well +ALTER TABLE Onek ADD CONSTRAINT onek_unique1_constraint UNIQUE (unique1); +NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "onek_unique1_constraint" for table "Onek" +ALTER INDEX onek_unique1_constraint RENAME TO onek_unique1_constraint_foo; +ALTER TABLE Onek DROP CONSTRAINT onek_unique1_constraint_foo; +-- renaming constraint +ALTER TABLE Onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0); +ALTER TABLE Onek RENAME CONSTRAINT onek_check_constraint TO onek_check_constraint_foo; +ALTER TABLE Onek DROP CONSTRAINT onek_check_constraint_foo; +-- renaming constraint should rename index as well +ALTER TABLE Onek ADD CONSTRAINT onek_unique1_constraint UNIQUE (unique1); +NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "onek_unique1_constraint" for table "Onek" +DROP INDEX onek_unique1_constraint; -- to see whether it's there +ERROR: cannot drop index onek_unique1_constraint because constraint onek_unique1_constraint on table "Onek" requires it +HINT: You can drop constraint onek_unique1_constraint on table "Onek" instead. +ALTER TABLE Onek RENAME CONSTRAINT onek_unique1_constraint TO onek_unique1_constraint_foo; +DROP INDEX onek_unique1_constraint_foo; -- to see whether it's there +ERROR: cannot drop index onek_unique1_constraint_foo because constraint onek_unique1_constraint_foo on table "Onek" requires it +HINT: You can drop constraint onek_unique1_constraint_foo on table "Onek" instead. +ALTER TABLE Onek DROP CONSTRAINT onek_unique1_constraint_foo; +-- renaming constraints vs. Inheritance +CREATE TABLE Constraint_Rename_Test (a int CONSTRAINT con1 CHECK (a > 0), b int, c int); +\d "Constraint_Rename_Test" +Table "public.Constraint_Rename_Test" + Column | Type | Modifiers +--------+---------+----------- + a | integer | + b | integer | + c | integer | +Check constraints: + "con1" CHECK (a > 0) + +CREATE TABLE Constraint_Rename_Test2 (a int CONSTRAINT con1 CHECK (a > 0), d int) InheRITS (Constraint_Rename_Test); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +\d "Constraint_Rename_Test2" +ALTER TABLE Constraint_Rename_Test2 RENAME CONSTRAINT con1 TO con1foo; -- fail +ERROR: relation "Constraint_Rename_Test2" does not exist +ALTER TABLE ONLY Constraint_Rename_Test RENAME CONSTRAINT con1 TO con1foo; -- fail +ALTER TABLE Constraint_Rename_Test RENAME CONSTRAINT con1 TO con1foo; -- ok +ERROR: constraint "con1" for table "Constraint_Rename_Test" does not exist +\d "Constraint_Rename_Test" +Table "public.Constraint_Rename_Test" + Column | Type | Modifiers +--------+---------+----------- + a | integer | + b | integer | + c | integer | +Check constraints: + "con1foo" CHECK (a > 0) + +\d "Constraint_Rename_Test2" +ALTER TABLE Constraint_Rename_Test ADD CONSTRAINT con2 CHECK (b > 0) NO InheRIT; +ALTER TABLE ONLY Constraint_Rename_Test RENAME CONSTRAINT con2 TO con2foo; -- ok +ALTER TABLE Constraint_Rename_Test RENAME CONSTRAINT con2foo TO con2bar; -- ok +\d "Constraint_Rename_Test" +Table "public.Constraint_Rename_Test" + Column | Type | Modifiers +--------+---------+----------- + a | integer | + b | integer | + c | integer | +Check constraints: + "con1foo" CHECK (a > 0) + "con2bar" CHECK (b > 0) NO INHERIT + +\d "Constraint_Rename_Test2" +ALTER TABLE Constraint_Rename_Test ADD CONSTRAINT con3 PRIMARY KEY (a); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "con3" for table "Constraint_Rename_Test" +ALTER TABLE Constraint_Rename_Test RENAME CONSTRAINT con3 TO con3foo; -- ok +\d "Constraint_Rename_Test" +Table "public.Constraint_Rename_Test" + Column | Type | Modifiers +--------+---------+----------- + a | integer | not null + b | integer | + c | integer | +Indexes: + "con3foo" PRIMARY KEY, btree (a) TABLESPACE pg_default +Check constraints: + "con1foo" CHECK (a > 0) + "con2bar" CHECK (b > 0) NO INHERIT + +\d "Constraint_Rename_Test2" +DROP TABLE Constraint_Rename_Test2; +ERROR: table "Constraint_Rename_Test2" does not exist +DROP TABLE Constraint_Rename_Test; +ALTER TABLE IF EXISTS Constraint_Rename_Test ADD CONSTRAINT con4 UNIQUE (a); +NOTICE: relation "Constraint_Rename_Test" does not exist, skipping +-- FOREIGN KEY CONSTRAINT adding TEST +CREATE TABLE Tmp2 (a int primary key); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Tmp2_pkey" for table "Tmp2" +CREATE TABLE Tmp3 (a int, b int); +CREATE TABLE Tmp4 (a int, b int, unique(a,b)); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "Tmp4_a_b_key" for table "Tmp4" +CREATE TABLE Tmp5 (a int, b int); +-- Insert rows into Tmp2 (PKTABLE) +INSERT INTO Tmp2 values (1); +INSERT INTO Tmp2 values (2); +INSERT INTO Tmp2 values (3); +INSERT INTO Tmp2 values (4); +-- Insert rows into Tmp3 +INSERT INTO Tmp3 values (1,10); +INSERT INTO Tmp3 values (1,20); +INSERT INTO Tmp3 values (5,50); +-- Try (and fail) to add constraint due to invalid source columns +ALTER TABLE Tmp3 add constraint tmpconstr foreign key(c) references Tmp2 match full; +ERROR: column "c" referenced in foreign key constraint does not exist +-- Try (and fail) to add constraint due to invalide destination columns explicitly given +ALTER TABLE Tmp3 add constraint tmpconstr foreign key(a) references Tmp2(b) match full; +ERROR: column "b" referenced in foreign key constraint does not exist +-- Try (and fail) to add constraint due to invalid data +ALTER TABLE Tmp3 add constraint tmpconstr foreign key (a) references Tmp2 match full; +ERROR: insert or update on table "Tmp3" violates foreign key constraint "tmpconstr" +DETAIL: Key (a)=(5) is not present in table "Tmp2". +-- Delete failing row +DELETE FROM Tmp3 where a=5; +-- Try (and succeed) +ALTER TABLE Tmp3 add constraint tmpconstr foreign key (a) references Tmp2 match full; +ALTER TABLE Tmp3 drop constraint tmpconstr; +INSERT INTO Tmp3 values (5,50); +-- Try NOT VALID and then VALIDATE CONSTRAINT, but fails. Delete failure then re-validate +ALTER TABLE Tmp3 add constraint tmpconstr foreign key (a) references Tmp2 match full NOT VALID; +ALTER TABLE Tmp3 validate constraint tmpconstr; +ERROR: insert or update on table "Tmp3" violates foreign key constraint "tmpconstr" +DETAIL: Key (a)=(5) is not present in table "Tmp2". +-- Delete failing row +DELETE FROM Tmp3 where a=5; +-- Try (and succeed) and repeat to show it works on already valid constraint +ALTER TABLE Tmp3 validate constraint tmpconstr; +ALTER TABLE Tmp3 validate constraint tmpconstr; +-- Try a non-verified CHECK constraint +ALTER TABLE Tmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10); -- fail +ERROR: check constraint "b_greater_than_ten" is violated by some row +ALTER TABLE Tmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10) NOT VALID; -- succeeds +ALTER TABLE Tmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- fails +ERROR: check constraint "b_greater_than_ten" is violated by some row +DELETE FROM Tmp3 WHERE NOT b > 10; +ALTER TABLE Tmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds +ALTER TABLE Tmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds +-- Test inherited NOT VALID CHECK constraints +select * from Tmp3; + a | b +---+---- + 1 | 20 +(1 row) + +CREATE TABLE Tmp6 () INHERITS (Tmp3); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +CREATE TABLE Tmp7 () INHERITS (Tmp3); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +INSERT INTO Tmp6 VALUES (6, 30), (7, 16); +ERROR: relation "Tmp6" does not exist on datanode1 +LINE 1: INSERT INTO Tmp6 VALUES (6, 30), (7, 16); + ^ +ALTER TABLE Tmp3 ADD CONSTRAINT b_le_20 CHECK (b <= 20) NOT VALID; +ALTER TABLE Tmp3 VALIDATE CONSTRAINT b_le_20; -- fails +DELETE FROM Tmp6 WHERE b > 20; +ERROR: relation "Tmp6" does not exist on datanode1 +LINE 1: DELETE FROM Tmp6 WHERE b > 20; + ^ +ALTER TABLE Tmp3 VALIDATE CONSTRAINT b_le_20; -- succeeds +-- An already validated constraint must not be revalidated +CREATE FUNCTION boo(int) RETURNS int IMMUTABLE STRICT LANGUAGE plpgsql AS $$ BEGIN RAISE NOTICE 'boo: %', $1; RETURN $1; END; $$; +INSERT INTO Tmp7 VALUES (8, 18); +ERROR: relation "Tmp7" does not exist on datanode1 +LINE 1: INSERT INTO Tmp7 VALUES (8, 18); + ^ +set client_min_messages=WARNING; +ALTER TABLE Tmp7 ADD CONSTRAINT identity CHECK (b = boo(b)); +ERROR: relation "Tmp7" does not exist +reset client_min_messages; +ALTER TABLE Tmp3 ADD CONSTRAINT IDENTITY check (b = boo(b)) NOT VALID; +set client_min_messages=WARNING; +ALTER TABLE Tmp3 VALIDATE CONSTRAINT identity; +reset client_min_messages; +-- Try (and fail) to create constraint from Tmp5(a) to Tmp4(a) - unique constraint on +-- Tmp4 is a,b +ALTER TABLE Tmp5 add constraint tmpconstr foreign key(a) references Tmp4(a) match full; +ERROR: there is no unique constraint matching given keys for referenced table "Tmp4" +DROP TABLE Tmp7; +ERROR: table "Tmp7" does not exist +DROP TABLE Tmp6; +ERROR: table "Tmp6" does not exist +DROP TABLE Tmp5; +DROP TABLE Tmp4; +DROP TABLE Tmp3; +DROP TABLE Tmp2; +-- NOT VALID with plan invalidation -- ensure we don't use a constraint for +-- exclusion until validated +set constraint_exclusion TO 'partition'; +create table NV_Parent (d date); +create table NV_Child_2010 () Inherits (NV_Parent); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +create table NV_Child_2011 () Inherits (NV_Parent); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +alter table NV_Child_2010 add check (d between '2010-01-01'::date and '2010-12-31'::date) not valid; +ERROR: relation "NV_Child_2010" does not exist +alter table NV_Child_2011 add check (d between '2011-01-01'::date and '2011-12-31'::date) not valid; +ERROR: relation "NV_Child_2011" does not exist +explain (costs off) select * from NV_Parent where d between '2011-08-01' and '2011-08-31'; +ERROR: invalid input syntax for type date: "2011" +LINE 1: ...osts off) select * from NV_Parent where d between '2011-08-0... + ^ +create table NV_Child_2009 (check (d between '2009-01-01'::date and '2009-12-31'::date)) Inherits (NV_Parent); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +explain (costs off) select * from NV_Parent where d between '2011-08-01'::date and '2011-08-31'::date; + QUERY PLAN +--------------------------------------------------------------------- + Seq Scan on "NV_Parent" + Filter: ((d >= '08-01-2011'::date) AND (d <= '08-31-2011'::date)) +(2 rows) + +explain (costs off) select * from NV_Parent where d between '2009-08-01'::date and '2009-08-31'::date; + QUERY PLAN +--------------------------------------------------------------------- + Seq Scan on "NV_Parent" + Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date)) +(2 rows) + +-- after validation, the constraint should be used +alter table NV_Child_2011 VALIDATE CONSTRAINT nv_child_2011_d_check; +ERROR: relation "NV_Child_2011" does not exist +explain (costs off) select * from NV_Parent where d between '2009-08-01'::date and '2009-08-31'::date; + QUERY PLAN +--------------------------------------------------------------------- + Seq Scan on "NV_Parent" + Filter: ((d >= '08-01-2009'::date) AND (d <= '08-31-2009'::date)) +(2 rows) + +-- Foreign key adding test with mixed types +-- Note: these tables are TEMP to avoid name conflicts when this test +-- is run in parallel with foreign_key.sql. +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +INSERT INTO PKTABLE VALUES(42); +CREATE TABLE FKTABLE (ftest1 inet); +-- This next should fail, because int=inet does not exist +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references PKTABLE; +ERROR: foreign key constraint "FKTABLE_ftest1_fkey" cannot be implemented +DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: inet and integer. +-- This should also fail for the same reason, but here we +-- give the column name +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references PKTABLE(ptest1); +ERROR: foreign key constraint "FKTABLE_ftest1_fkey" cannot be implemented +DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: inet and integer. +DROP TABLE FKTABLE; +-- This should succeed, even though they are different types, +-- because int=int8 exists and is a member of the integer opfamily +CREATE TABLE FKTABLE (ftest1 int8); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references PKTABLE; +-- Check it actually works +INSERT INTO FKTABLE VALUES(42); -- should succeed +INSERT INTO FKTABLE VALUES(43); -- should fail +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_ftest1_fkey" +DETAIL: Key (ftest1)=(43) is not present in table "PKTABLE". +DROP TABLE FKTABLE; +-- This should fail, because we'd have to cast numeric to int which is +-- not an implicit coercion (or use numeric=numeric, but that's not part +-- of the integer opfamily) +CREATE TABLE FKTABLE (ftest1 numeric); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references PKTABLE; +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +-- On the other hand, this should work because int implicitly promotes to +-- numeric, and we allow promotion on the FK side +CREATE TABLE PKTABLE (ptest1 numeric PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +INSERT INTO PKTABLE VALUES(42); +CREATE TABLE FKTABLE (ftest1 int); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references PKTABLE; +-- Check it actually works +INSERT INTO FKTABLE VALUES(42); -- should succeed +INSERT INTO FKTABLE VALUES(43); -- should fail +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_ftest1_fkey" +DETAIL: Key (ftest1)=(43) is not present in table "PKTABLE". +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, + PRIMARY KEY(ptest1, ptest2)); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +-- This should fail, because we just chose really odd types +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references PKTABLE; +ERROR: foreign key constraint "FKTABLE_ftest1_fkey" cannot be implemented +DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: cidr and integer. +DROP TABLE FKTABLE; +-- Again, so should this... +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) + references PKTABLE(ptest1, ptest2); +ERROR: foreign key constraint "FKTABLE_ftest1_fkey" cannot be implemented +DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: cidr and integer. +DROP TABLE FKTABLE; +-- This fails because we mixed up the column ordering +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) + references PKTABLE(ptest2, ptest1); +ERROR: foreign key constraint "FKTABLE_ftest1_fkey" cannot be implemented +DETAIL: Key columns "ftest1" and "ptest2" are of incompatible types: integer and inet. +-- As does this... +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest2, ftest1) + references PKTABLE(ptest1, ptest2); +ERROR: foreign key constraint "FKTABLE_ftest2_fkey" cannot be implemented +DETAIL: Key columns "ftest2" and "ptest1" are of incompatible types: inet and integer. +-- temp tables should go away by themselves, need not drop them. diff --git a/contrib/dolphin/expected/case_sensitive_test/analyze_commands.out b/contrib/dolphin/expected/case_sensitive_test/analyze_commands.out new file mode 100644 index 0000000000000000000000000000000000000000..9d8a40dcab61085bacc6315535555af3b1351f35 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/analyze_commands.out @@ -0,0 +1,92 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +create schema analyze_commands; +set search_path to analyze_commands; +drop table if exists T1; +NOTICE: table "T1" does not exist, skipping +create table T1(a int, b int, c int); +insert into T1 values(generate_series(1,10),generate_series(1,2),generate_series(1,2)); +set default_statistics_target=100; +analyze T1; +analyze T1((b,c)); +INFO: Please set default_statistics_target to a negative value to collect extended statistics. +select * from pg_stats where tablename = 'T1' order by attname; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | n_dndistinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram +------------------+-----------+---------+-----------+-----------+-----------+------------+--------------+------------------+-------------------+------------------------+-------------+-------------------+------------------------+---------------------- + analyze_commands | T1 | a | f | 0 | 4 | -1 | 0 | | | {1,2,3,4,5,6,7,8,9,10} | 1 | | | + analyze_commands | T1 | b | f | 0 | 4 | -0.2 | 0 | {1,2} | {0.5,0.5} | | 0.636364 | | | + analyze_commands | T1 | c | f | 0 | 4 | -0.2 | 0 | {1,2} | {0.5,0.5} | | 0.636364 | | | +(3 rows) + +select * from pg_catalog.pg_ext_stats; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | n_dndistinct | most_common_vals | most_common_freqs | most_common_vals_null | most_common_freqs_null | histogram_bounds +------------+-----------+---------+-----------+-----------+-----------+------------+--------------+------------------+-------------------+-----------------------+------------------------+------------------ +(0 rows) + +drop table if exists T1; +create table T1(a int, b int, c int); +insert into T1 values(generate_series(1,10),generate_series(1,2),generate_series(1,2)); +set default_statistics_target=100; +analyze; +INFO: Please set default_statistics_target to a negative value to collect extended statistics. +INFO: Please set default_statistics_target to a negative value to collect extended statistics. +INFO: Please set default_statistics_target to a negative value to collect extended statistics. +INFO: Please set default_statistics_target to a negative value to collect extended statistics. +select * from pg_stats where tablename = 'T1' order by attname; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | n_dndistinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram +------------------+-----------+---------+-----------+-----------+-----------+------------+--------------+------------------+-------------------+------------------------+-------------+-------------------+------------------------+---------------------- + analyze_commands | T1 | a | f | 0 | 4 | -1 | 0 | | | {1,2,3,4,5,6,7,8,9,10} | 1 | | | + analyze_commands | T1 | b | f | 0 | 4 | -0.2 | 0 | {1,2} | {0.5,0.5} | | 0.636364 | | | + analyze_commands | T1 | c | f | 0 | 4 | -0.2 | 0 | {1,2} | {0.5,0.5} | | 0.636364 | | | +(3 rows) + +select * from pg_catalog.pg_ext_stats; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | n_dndistinct | most_common_vals | most_common_freqs | most_common_vals_null | most_common_freqs_null | histogram_bounds +------------+-----------+---------+-----------+-----------+-----------+------------+--------------+------------------+-------------------+-----------------------+------------------------+------------------ +(0 rows) + +drop table if exists T1; +create table T1(a int, b int, c int); +insert into T1 values(generate_series(1,10),generate_series(1,2),generate_series(1,2)); +set default_statistics_target=-2; +analyze T1; +analyze T1((b,c)); +select * from pg_stats where tablename = 'T1' order by attname; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | n_dndistinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram +------------------+-----------+---------+-----------+-----------+-----------+------------+--------------+------------------+-------------------+------------------------+-------------+-------------------+------------------------+---------------------- + analyze_commands | T1 | a | f | 0 | 4 | -1 | 0 | | | {1,2,3,4,5,6,7,8,9,10} | 1 | | | + analyze_commands | T1 | b | f | 0 | 4 | -0.2 | 0 | {1,2} | {0.5,0.5} | | 0.636364 | | | + analyze_commands | T1 | c | f | 0 | 4 | -0.2 | 0 | {1,2} | {0.5,0.5} | | 0.636364 | | | +(3 rows) + +select * from pg_catalog.pg_ext_stats; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | n_dndistinct | most_common_vals | most_common_freqs | most_common_vals_null | most_common_freqs_null | histogram_bounds +------------------+-----------+---------+-----------+-----------+-----------+------------+--------------+-------------------+-------------------+-----------------------+------------------------+------------------ + analyze_commands | T1 | 2 3 | f | 0 | 8 | -0.2 | 0 | {"{1,2}","{1,2}"} | {0.5,0.5} | | | +(1 row) + +insert into T1 values(generate_series(1,10),generate_series(3,4),generate_series(3,4)); +analyze; +--?.* +--?.* +--?.* +--?.* +--?.* +--?.* +select * from pg_stats where tablename = 'T1' order by attname; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | n_dndistinct | most_common_vals | most_common_freqs | histogram_bounds | correlation | most_common_elems | most_common_elem_freqs | elem_count_histogram +------------------+-----------+---------+-----------+-----------+-----------+------------+--------------+------------------------+-------------------------------------------+------------------+-------------+-------------------+------------------------+---------------------- + analyze_commands | T1 | a | f | 0 | 4 | -0.5 | 0 | {1,2,3,4,5,6,7,8,9,10} | {0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1,0.1} | | | | | + analyze_commands | T1 | b | f | 0 | 4 | -0.2 | 0 | {1,2,3,4} | {0.25,0.25,0.25,0.25} | | | | | + analyze_commands | T1 | c | f | 0 | 4 | -0.2 | 0 | {1,2,3,4} | {0.25,0.25,0.25,0.25} | | | | | +(3 rows) + +select * from pg_catalog.pg_ext_stats; + schemaname | tablename | attname | inherited | null_frac | avg_width | n_distinct | n_dndistinct | most_common_vals | most_common_freqs | most_common_vals_null | most_common_freqs_null | histogram_bounds +------------------+-----------+---------+-----------+-----------+-----------+------------+--------------+---------------------------+-----------------------+-----------------------+------------------------+------------------ + analyze_commands | T1 | 2 3 | f | 0 | 8 | -0.2 | 0 | {"{1,2,3,4}","{1,2,3,4}"} | {0.25,0.25,0.25,0.25} | | | +(1 row) + +reset search_path; +drop schema analyze_commands cascade; +NOTICE: drop cascades to table analyze_commands."T1" diff --git a/contrib/dolphin/expected/case_sensitive_test/cluster.out b/contrib/dolphin/expected/case_sensitive_test/cluster.out new file mode 100644 index 0000000000000000000000000000000000000000..6fcc7582711572582d102c396ecf3a70f4dc7c83 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/cluster.out @@ -0,0 +1,451 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- CLUSTER +-- +CREATE TABLE Clstr_tst_s (rf_a SERIAL PRIMARY KEY, + b INT); +NOTICE: CREATE TABLE will create implicit sequence "Clstr_tst_s_rf_a_seq" for serial column "Clstr_tst_s.rf_a" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Clstr_tst_s_pkey" for table "Clstr_tst_s" +CREATE TABLE Clstr_tst (a SERIAL PRIMARY KEY, + b INT, + c TEXT, + d TEXT + ); +NOTICE: CREATE TABLE will create implicit sequence "Clstr_tst_a_seq" for serial column "Clstr_tst.a" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Clstr_tst_pkey" for table "Clstr_tst" +CREATE INDEX Clstr_tst_b ON Clstr_tst (b); +CREATE INDEX Clstr_tst_c ON Clstr_tst (c); +CREATE INDEX Clstr_tst_c_b ON Clstr_tst (c,b); +CREATE INDEX Clstr_tst_b_c ON Clstr_tst (b,c); +INSERT INTO Clstr_tst_s (b) VALUES (0); +INSERT INTO Clstr_tst_s (b) SELECT b FROM Clstr_tst_s; +INSERT INTO Clstr_tst_s (b) SELECT b FROM Clstr_tst_s; +INSERT INTO Clstr_tst_s (b) SELECT b FROM Clstr_tst_s; +INSERT INTO Clstr_tst_s (b) SELECT b FROM Clstr_tst_s; +INSERT INTO Clstr_tst_s (b) SELECT b FROM Clstr_tst_s; +-- CREATE TABLE Clstr_tst_inh () INHERITS (Clstr_tst); +INSERT INTO Clstr_tst (b, c) VALUES (11, 'once'); +INSERT INTO Clstr_tst (b, c) VALUES (10, 'diez'); +INSERT INTO Clstr_tst (b, c) VALUES (31, 'treinta y uno'); +INSERT INTO Clstr_tst (b, c) VALUES (22, 'veintidos'); +INSERT INTO Clstr_tst (b, c) VALUES (3, 'tres'); +INSERT INTO Clstr_tst (b, c) VALUES (20, 'veinte'); +INSERT INTO Clstr_tst (b, c) VALUES (23, 'veintitres'); +INSERT INTO Clstr_tst (b, c) VALUES (21, 'veintiuno'); +INSERT INTO Clstr_tst (b, c) VALUES (4, 'cuatro'); +INSERT INTO Clstr_tst (b, c) VALUES (14, 'catorce'); +INSERT INTO Clstr_tst (b, c) VALUES (2, 'dos'); +INSERT INTO Clstr_tst (b, c) VALUES (18, 'dieciocho'); +INSERT INTO Clstr_tst (b, c) VALUES (27, 'veintisiete'); +INSERT INTO Clstr_tst (b, c) VALUES (25, 'veinticinco'); +INSERT INTO Clstr_tst (b, c) VALUES (13, 'trece'); +INSERT INTO Clstr_tst (b, c) VALUES (28, 'veintiocho'); +INSERT INTO Clstr_tst (b, c) VALUES (32, 'treinta y dos'); +INSERT INTO Clstr_tst (b, c) VALUES (5, 'cinco'); +INSERT INTO Clstr_tst (b, c) VALUES (29, 'veintinueve'); +INSERT INTO Clstr_tst (b, c) VALUES (1, 'uno'); +INSERT INTO Clstr_tst (b, c) VALUES (24, 'veinticuatro'); +INSERT INTO Clstr_tst (b, c) VALUES (30, 'treinta'); +INSERT INTO Clstr_tst (b, c) VALUES (12, 'doce'); +INSERT INTO Clstr_tst (b, c) VALUES (17, 'diecisiete'); +INSERT INTO Clstr_tst (b, c) VALUES (9, 'nueve'); +INSERT INTO Clstr_tst (b, c) VALUES (19, 'diecinueve'); +INSERT INTO Clstr_tst (b, c) VALUES (26, 'veintiseis'); +INSERT INTO Clstr_tst (b, c) VALUES (15, 'quince'); +INSERT INTO Clstr_tst (b, c) VALUES (7, 'siete'); +INSERT INTO Clstr_tst (b, c) VALUES (16, 'dieciseis'); +INSERT INTO Clstr_tst (b, c) VALUES (8, 'ocho'); +-- This entry is needed to test that TOASTED values are copied correctly. +INSERT INTO Clstr_tst (b, c, d) VALUES (6, 'seis', repeat('xyzzy', 100000)); +CLUSTER Clstr_tst_c ON Clstr_tst; +SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a, b, c; + a | b | c | substring | length +----+----+---------------+--------------------------------+-------- + 1 | 11 | once | | + 2 | 10 | diez | | + 3 | 31 | treinta y uno | | + 4 | 22 | veintidos | | + 5 | 3 | tres | | + 6 | 20 | veinte | | + 7 | 23 | veintitres | | + 8 | 21 | veintiuno | | + 9 | 4 | cuatro | | + 10 | 14 | catorce | | + 11 | 2 | dos | | + 12 | 18 | dieciocho | | + 13 | 27 | veintisiete | | + 14 | 25 | veinticinco | | + 15 | 13 | trece | | + 16 | 28 | veintiocho | | + 17 | 32 | treinta y dos | | + 18 | 5 | cinco | | + 19 | 29 | veintinueve | | + 20 | 1 | uno | | + 21 | 24 | veinticuatro | | + 22 | 30 | treinta | | + 23 | 12 | doce | | + 24 | 17 | diecisiete | | + 25 | 9 | nueve | | + 26 | 19 | diecinueve | | + 27 | 26 | veintiseis | | + 28 | 15 | quince | | + 29 | 7 | siete | | + 30 | 16 | dieciseis | | + 31 | 8 | ocho | | + 32 | 6 | seis | xyzzyxyzzyxyzzyxyzzyxyzzyxyzzy | 500000 +(32 rows) + +SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a; + a | b | c | substring | length +----+----+---------------+--------------------------------+-------- + 1 | 11 | once | | + 2 | 10 | diez | | + 3 | 31 | treinta y uno | | + 4 | 22 | veintidos | | + 5 | 3 | tres | | + 6 | 20 | veinte | | + 7 | 23 | veintitres | | + 8 | 21 | veintiuno | | + 9 | 4 | cuatro | | + 10 | 14 | catorce | | + 11 | 2 | dos | | + 12 | 18 | dieciocho | | + 13 | 27 | veintisiete | | + 14 | 25 | veinticinco | | + 15 | 13 | trece | | + 16 | 28 | veintiocho | | + 17 | 32 | treinta y dos | | + 18 | 5 | cinco | | + 19 | 29 | veintinueve | | + 20 | 1 | uno | | + 21 | 24 | veinticuatro | | + 22 | 30 | treinta | | + 23 | 12 | doce | | + 24 | 17 | diecisiete | | + 25 | 9 | nueve | | + 26 | 19 | diecinueve | | + 27 | 26 | veintiseis | | + 28 | 15 | quince | | + 29 | 7 | siete | | + 30 | 16 | dieciseis | | + 31 | 8 | ocho | | + 32 | 6 | seis | xyzzyxyzzyxyzzyxyzzyxyzzyxyzzy | 500000 +(32 rows) + +SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY b; + a | b | c | substring | length +----+----+---------------+--------------------------------+-------- + 20 | 1 | uno | | + 11 | 2 | dos | | + 5 | 3 | tres | | + 9 | 4 | cuatro | | + 18 | 5 | cinco | | + 32 | 6 | seis | xyzzyxyzzyxyzzyxyzzyxyzzyxyzzy | 500000 + 29 | 7 | siete | | + 31 | 8 | ocho | | + 25 | 9 | nueve | | + 2 | 10 | diez | | + 1 | 11 | once | | + 23 | 12 | doce | | + 15 | 13 | trece | | + 10 | 14 | catorce | | + 28 | 15 | quince | | + 30 | 16 | dieciseis | | + 24 | 17 | diecisiete | | + 12 | 18 | dieciocho | | + 26 | 19 | diecinueve | | + 6 | 20 | veinte | | + 8 | 21 | veintiuno | | + 4 | 22 | veintidos | | + 7 | 23 | veintitres | | + 21 | 24 | veinticuatro | | + 14 | 25 | veinticinco | | + 27 | 26 | veintiseis | | + 13 | 27 | veintisiete | | + 16 | 28 | veintiocho | | + 19 | 29 | veintinueve | | + 22 | 30 | treinta | | + 3 | 31 | treinta y uno | | + 17 | 32 | treinta y dos | | +(32 rows) + +SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY c; + a | b | c | substring | length +----+----+---------------+--------------------------------+-------- + 10 | 14 | catorce | | + 18 | 5 | cinco | | + 9 | 4 | cuatro | | + 26 | 19 | diecinueve | | + 12 | 18 | dieciocho | | + 30 | 16 | dieciseis | | + 24 | 17 | diecisiete | | + 2 | 10 | diez | | + 23 | 12 | doce | | + 11 | 2 | dos | | + 25 | 9 | nueve | | + 31 | 8 | ocho | | + 1 | 11 | once | | + 28 | 15 | quince | | + 32 | 6 | seis | xyzzyxyzzyxyzzyxyzzyxyzzyxyzzy | 500000 + 29 | 7 | siete | | + 15 | 13 | trece | | + 22 | 30 | treinta | | + 17 | 32 | treinta y dos | | + 3 | 31 | treinta y uno | | + 5 | 3 | tres | | + 20 | 1 | uno | | + 6 | 20 | veinte | | + 14 | 25 | veinticinco | | + 21 | 24 | veinticuatro | | + 4 | 22 | veintidos | | + 19 | 29 | veintinueve | | + 16 | 28 | veintiocho | | + 27 | 26 | veintiseis | | + 13 | 27 | veintisiete | | + 7 | 23 | veintitres | | + 8 | 21 | veintiuno | | +(32 rows) + +-- Verify that inheritance link still works +-- INSERT INTO Clstr_tst_inh VALUES (0, 100, 'in child table'); +SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a, b, c; + a | b | c | substring | length +----+----+---------------+--------------------------------+-------- + 1 | 11 | once | | + 2 | 10 | diez | | + 3 | 31 | treinta y uno | | + 4 | 22 | veintidos | | + 5 | 3 | tres | | + 6 | 20 | veinte | | + 7 | 23 | veintitres | | + 8 | 21 | veintiuno | | + 9 | 4 | cuatro | | + 10 | 14 | catorce | | + 11 | 2 | dos | | + 12 | 18 | dieciocho | | + 13 | 27 | veintisiete | | + 14 | 25 | veinticinco | | + 15 | 13 | trece | | + 16 | 28 | veintiocho | | + 17 | 32 | treinta y dos | | + 18 | 5 | cinco | | + 19 | 29 | veintinueve | | + 20 | 1 | uno | | + 21 | 24 | veinticuatro | | + 22 | 30 | treinta | | + 23 | 12 | doce | | + 24 | 17 | diecisiete | | + 25 | 9 | nueve | | + 26 | 19 | diecinueve | | + 27 | 26 | veintiseis | | + 28 | 15 | quince | | + 29 | 7 | siete | | + 30 | 16 | dieciseis | | + 31 | 8 | ocho | | + 32 | 6 | seis | xyzzyxyzzyxyzzyxyzzyxyzzyxyzzy | 500000 +(32 rows) + +-- Verify that foreign key link still works +INSERT INTO Clstr_tst (b, c) VALUES (1111, 'this should fail'); +SELECT conname FROM pg_constraint WHERE conrelid = 'Clstr_tst'::regclass +ORDER BY 1; +ERROR: relation "clstr_tst" does not exist +LINE 1: ...ELECT conname FROM pg_constraint WHERE conrelid = 'Clstr_tst... + ^ +SELECT relname, relkind, + EXISTS(SELECT 1 FROM pg_class WHERE oid = c.reltoastrelid) AS hastoast +FROM pg_class c WHERE relname LIKE 'Clstr_tst%' ORDER BY relname; + relname | relkind | hastoast +----------------------+---------+---------- + Clstr_tst | r | t + Clstr_tst_a_seq | S | f + Clstr_tst_pkey | i | f + Clstr_tst_s | r | f + Clstr_tst_s_pkey | i | f + Clstr_tst_s_rf_a_seq | S | f +(6 rows) + +-- Verify that indisclustered is correctly set +SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2 +WHERE pg_class.oid=indexrelid + AND indrelid=pg_class_2.oid + AND pg_class_2.relname = 'Clstr_tst' + AND indisclustered; + relname +------------- + clstr_tst_c +(1 row) + +-- Try changing indisclustered +ALTER TABLE Clstr_tst CLUSTER ON Clstr_tst_b_c; +SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2 +WHERE pg_class.oid=indexrelid + AND indrelid=pg_class_2.oid + AND pg_class_2.relname = 'Clstr_tst' + AND indisclustered; + relname +--------------- + clstr_tst_b_c +(1 row) + +-- Try turning off all clustering +ALTER TABLE Clstr_tst SET WITHOUT CLUSTER; +SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2 +WHERE pg_class.oid=indexrelid + AND indrelid=pg_class_2.oid + AND pg_class_2.relname = 'Clstr_tst' + AND indisclustered; + relname +--------- +(0 rows) + +-- Verify that clustering all tables does in fact cluster the right ones +CREATE USER Clstr_user PASSWORD 'ttest@123'; +CREATE TABLE Clstr_1 (a INT PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Clstr_1_pkey" for table "Clstr_1" +CREATE TABLE Clstr_2 (a INT PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Clstr_2_pkey" for table "Clstr_2" +CREATE TABLE Clstr_3 (a INT PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Clstr_3_pkey" for table "Clstr_3" +ALTER TABLE Clstr_1 OWNER TO Clstr_user; +ALTER TABLE Clstr_3 OWNER TO Clstr_user; +GRANT SELECT ON Clstr_2 TO Clstr_user; +INSERT INTO Clstr_1 VALUES (2); +INSERT INTO Clstr_1 VALUES (1); +INSERT INTO Clstr_2 VALUES (2); +INSERT INTO Clstr_2 VALUES (1); +INSERT INTO Clstr_3 VALUES (2); +INSERT INTO Clstr_3 VALUES (1); +-- "CLUSTER " on a table that hasn't been clustered +CLUSTER Clstr_2; +ERROR: there is no previously clustered index for table "Clstr_2" +CLUSTER Clstr_1_pkey ON Clstr_1; +ERROR: index "clstr_1_pkey" for table "Clstr_1" does not exist +CLUSTER Clstr_2 USING Clstr_2_pkey; +ERROR: index "clstr_2_pkey" for table "Clstr_2" does not exist +SELECT * FROM Clstr_1 UNION ALL + SELECT * FROM Clstr_2 UNION ALL + SELECT * FROM Clstr_3 + ORDER BY 1; + a +--- + 1 + 1 + 1 + 2 + 2 + 2 +(6 rows) + +-- revert to the original state +DELETE FROM Clstr_1; +DELETE FROM Clstr_2; +DELETE FROM Clstr_3; +INSERT INTO Clstr_1 VALUES (2); +INSERT INTO Clstr_1 VALUES (1); +INSERT INTO Clstr_2 VALUES (2); +INSERT INTO Clstr_2 VALUES (1); +INSERT INTO Clstr_3 VALUES (2); +INSERT INTO Clstr_3 VALUES (1); +-- this user can only cluster Clstr_1 and Clstr_3, but the latter +-- has not been clustered +SET SESSION AUTHORIZATION Clstr_user PASSWORD 'ttest@123'; +ERROR: Invalid username/password,set session_authorization denied. +CLUSTER; +SELECT * FROM Clstr_1 UNION ALL + SELECT * FROM Clstr_2 UNION ALL + SELECT * FROM Clstr_3 + ORDER BY 1; + a +--- + 1 + 1 + 1 + 2 + 2 + 2 +(6 rows) + +-- cluster a single table using the indisclustered bit previously set +DELETE FROM Clstr_1; +INSERT INTO Clstr_1 VALUES (2); +INSERT INTO Clstr_1 VALUES (1); +CLUSTER Clstr_1; +ERROR: there is no previously clustered index for table "Clstr_1" +SELECT * FROM Clstr_1 +ORDER BY 1; + a +--- + 1 + 2 +(2 rows) + +-- Test MVCC-safety of cluster. There isn't much we can do to verify the +-- results with a single backend... +CREATE TABLE clustertest (key_a int PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "clustertest_pkey" for table "clustertest" +INSERT INTO clustertest VALUES (10); +INSERT INTO clustertest VALUES (20); +INSERT INTO clustertest VALUES (30); +INSERT INTO clustertest VALUES (40); +INSERT INTO clustertest VALUES (50); +-- Use a transaction so that updates are not committed when CLUSTER sees 'em +START TRANSACTION; +-- Test update where the old row version is found first in the scan +UPDATE clustertest SET key_a = 100 WHERE key_a = 10; +-- Test update where the new row version is found first in the scan +UPDATE clustertest SET key_a = 35 WHERE key_a = 40; +-- Test longer update chain +UPDATE clustertest SET key_a = 60 WHERE key_a = 50; +UPDATE clustertest SET key_a = 70 WHERE key_a = 60; +UPDATE clustertest SET key_a = 80 WHERE key_a = 70; +SELECT * FROM clustertest ORDER BY 1; + key_a +------- + 20 + 30 + 35 + 80 + 100 +(5 rows) + +CLUSTER clustertest_pkey ON clustertest; +ERROR: CLUSTER cannot run inside a transaction block +SELECT * FROM clustertest ORDER BY 1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +COMMIT; +SELECT * FROM clustertest ORDER BY 1; + key_a +------- + 10 + 20 + 30 + 40 + 50 +(5 rows) + +-- check that temp tables can be clustered +-- Enforce use of COMMIT instead of 2PC for temporary objects +RESET SESSION AUTHORIZATION; +SET SESSION AUTHORIZATION Clstr_user PASSWORD 'ttest@123'; +ERROR: Invalid username/password,set session_authorization denied. +create temp table Clstr_temp (col1 int primary key, col2 text); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Clstr_temp_pkey" for table "Clstr_temp" +insert into Clstr_temp values (2, 'two'), (1, 'one'); +cluster Clstr_temp using Clstr_temp_pkey; +ERROR: index "clstr_temp_pkey" for table "Clstr_temp" does not exist +select * from Clstr_temp order by 1; + col1 | col2 +------+------ + 1 | one + 2 | two +(2 rows) + +drop table Clstr_temp; +DROP TABLE Clstr_2; +DROP TABLE Clstr_tst_s; +-- clean up +\c - +RESET SESSION AUTHORIZATION; +DROP USER "Clstr_user" CASCADE; diff --git a/contrib/dolphin/expected/case_sensitive_test/create_foreign_table.out b/contrib/dolphin/expected/case_sensitive_test/create_foreign_table.out new file mode 100644 index 0000000000000000000000000000000000000000..159a15ed5bcbef703c35f5f3073bd45bff2d6014 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/create_foreign_table.out @@ -0,0 +1,73 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +--Create Foreign table in Normal mode. +-- +create foreign table Foreign_t1 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'text', location 'gsfs://127.0.0.1:12345/t1.data', delimiter '|'); +ERROR: Un-supported feature +DETAIL: Gauss Data Service(GDS) are not supported in single node mode. +create foreign table Foreign_t2 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'csv', location 'gsfs://127.0.0.1:12345/t1.data', delimiter '|', mode 'normal'); +ERROR: Un-supported feature +DETAIL: Gauss Data Service(GDS) are not supported in single node mode. +-- +--Create Foreign table in Shared mode +-- +create foreign table Foreign_t3 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'text', location 'gsfs://127.0.0.1:12345/t1.data', delimiter '|', mode 'shared'); +ERROR: SHARED mode can not use location "gsfs://127.0.0.1:12345/t1.data" +create foreign table Foreign_t4 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'csv', location '/data/t1.data', delimiter '|', mode 'shared'); +ERROR: SHARED mode can not be used with CSV format +create foreign table Foreign_t5 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'text', location '/data/t1.data', delimiter '|', mode 'shared'); +-- +--Create Foreign table in Private mode +-- +create foreign table Foreign_t6 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'text', location '/data/t1.data', delimiter '|', mode 'private'); +create foreign table Foreign_t7 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'csv', location '/data/t1.data', delimiter '|', mode 'private'); +create foreign table Foreign_t8 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'csv', location 'gsfs://127.0.0.1:12345/t1.data', delimiter '|', mode 'private'); +ERROR: PRIVATE mode can not use location "gsfs://127.0.0.1:12345/t1.data" +----- +create foreign table Foreign_t9 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'csv', location '/data/t1.data', delimiter '|', mode 'private', fill_missing_fields 'true'); +drop foreign table Foreign_t1; +ERROR: foreign table "foreign_t1" does not exist +drop foreign table Foreign_t2; +ERROR: foreign table "foreign_t2" does not exist +drop foreign table Foreign_t3; +ERROR: foreign table "foreign_t3" does not exist +drop foreign table Foreign_t4; +ERROR: foreign table "foreign_t4" does not exist +drop foreign table Foreign_t5; +ERROR: foreign table "foreign_t5" does not exist +drop foreign table Foreign_t6; +ERROR: foreign table "foreign_t6" does not exist +drop foreign table Foreign_t7; +ERROR: foreign table "foreign_t7" does not exist +drop foreign table Foreign_t8; +ERROR: foreign table "foreign_t8" does not exist +drop foreign table Foreign_t9; +ERROR: foreign table "foreign_t9" does not exist diff --git a/contrib/dolphin/expected/case_sensitive_test/create_index.out b/contrib/dolphin/expected/case_sensitive_test/create_index.out new file mode 100644 index 0000000000000000000000000000000000000000..d37dedf28bba7a84c1415ee20a54e1dd8ec5cda9 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/create_index.out @@ -0,0 +1,1866 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- CREATE_INDEX +-- Create ancillary data structures (i.e. indices) +-- +-- +-- BTREE +-- +CREATE INDEX onek_unique1 ON Onek USING btree(unique1 int4_ops); +CREATE INDEX onek_unique2 ON Onek USING btree(unique2 int4_ops); +CREATE INDEX onek_hundred ON Onek USING btree(hundred int4_ops); +CREATE INDEX onek_stringu1 ON Onek USING btree(stringu1 name_ops); +CREATE INDEX tenk1_unique1 ON Tenk1 USING btree(unique1 int4_ops); +CREATE INDEX tenk1_unique2 ON Tenk1 USING btree(unique2 int4_ops); +CREATE INDEX tenk1_hundred ON Tenk1 USING btree(hundred int4_ops); +CREATE INDEX tenk1_thous_tenthous ON Tenk1 (thousand, tenthous); +CREATE INDEX tenk2_unique1 ON Tenk2 USING btree(unique1 int4_ops); +CREATE INDEX tenk2_unique2 ON Tenk2 USING btree(unique2 int4_ops); +CREATE INDEX tenk2_hundred ON Tenk2 USING btree(hundred int4_ops); +CREATE INDEX rix ON Road USING btree (name text_ops); +CREATE INDEX iix ON iHighway USING btree (name text_ops); +CREATE INDEX six ON sHighway USING btree (name text_ops); +-- test comments +COMMENT ON INDEX six_wrong IS 'bad index'; +ERROR: relation "six_wrong" does not exist +COMMENT ON INDEX six IS 'good index'; +COMMENT ON INDEX six IS NULL; +-- +-- BTREE ascending/descending cases +-- +-- we load int4/text from pure descending data (each key is a new +-- low key) and name/f8 from pure ascending data (each key is a new +-- high key). we had a bug where new low keys would sometimes be +-- "lost". +-- +CREATE INDEX bt_i4_index ON BT_i4_heap USING btree (seqno int4_ops); +CREATE INDEX bt_name_index ON BT_name_heap USING btree (seqno name_ops); +CREATE INDEX bt_txt_index ON BT_txt_heap USING btree (seqno text_ops); +CREATE INDEX bt_f8_index ON BT_f8_heap USING btree (seqno float8_ops); +-- +-- BTREE partial indices +-- +CREATE INDEX onek2_u1_prtl ON Onek2 USING btree(unique1 int4_ops) + where unique1 < 20 or unique1 > 980; +CREATE INDEX onek2_u2_prtl ON Onek2 USING btree(unique2 int4_ops) + where stringu1 < 'B'; +CREATE INDEX onek2_stu1_prtl ON Onek2 USING btree(stringu1 name_ops) + where Onek2.stringu1 >= 'J' and Onek2.stringu1 < 'K'; +-- +-- GiST (rtree-equivalent opclasses only) +-- +CREATE INDEX grect2ind ON Fast_emp4000 USING gist (home_base); +CREATE INDEX gpolygonind ON Polygon_tbl USING gist (f1); +ERROR: relation "Polygon_tbl" does not exist +CREATE INDEX gcircleind ON Circle_tbl USING gist (f1); +ERROR: relation "Circle_tbl" does not exist +INSERT INTO point_tbl(f1) VALUES (NULL); +CREATE INDEX gpointind ON point_tbl USING gist (f1); +--CREATE TABLE gPolygon_tbl AS +-- SELECT polygon(home_base) AS f1 FROM Slow_emp4000; +--INSERT INTO gPolygon_tbl VALUES ( '(1000,0,0,1000)' ); +--INSERT INTO gPolygon_tbl VALUES ( '(0,1000,1000,1000)' ); +--CREATE TABLE gCircle_tbl AS +-- SELECT circle(home_base) AS f1 FROM Slow_emp4000; +--CREATE INDEX ggpolygonind ON gPolygon_tbl USING gist (f1); +--CREATE INDEX ggcircleind ON gCircle_tbl USING gist (f1); +-- +-- SP-GiST +-- +CREATE TABLE Quad_point_tbl AS + SELECT point(unique1,unique2) AS p FROM Tenk1; +INSERT INTO Quad_point_tbl + SELECT '(333.0,400.0)'::point FROM generate_series(1,1000); +INSERT INTO Quad_point_tbl VALUES (NULL), (NULL), (NULL); +CREATE INDEX sp_quad_ind ON Quad_point_tbl USING spgist (p); +ERROR: access method "spgist" does not support row store +CREATE TABLE KD_point_tbl AS SELECT * FROM Quad_point_tbl; +CREATE INDEX SP_kd_ind ON KD_point_tbl USING spgist (p kd_point_ops); +ERROR: access method "spgist" does not support row store +CREATE TABLE Suffix_text_tbl AS + SELECT name AS t FROM Road WHERE name !~ '^[0-9]'; +INSERT INTO Suffix_text_tbl + SELECT 'P0123456789abcdef' FROM generate_series(1,1000); +INSERT INTO Suffix_text_tbl VALUES ('P0123456789abcde'); +INSERT INTO Suffix_text_tbl VALUES ('P0123456789abcdefF'); +CREATE INDEX sp_suff_ind ON Suffix_text_tbl USING spgist (t); +ERROR: access method "spgist" does not support row store +-- +-- Test GiST and SP-GiST indexes +-- +-- get non-indexed results for comparison purposes +SET enable_seqscan = ON; +SET enable_indexscan = OFF; +SET enable_bitmapscan = OFF; +SELECT * FROM Fast_emp4000 + WHERE home_base @ '(200,200),(2000,1000)'::box + ORDER BY (home_base[0])[0]; + home_base +----------- +(0 rows) + +SELECT count(*) FROM Fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Fast_emp4000 WHERE home_base IS NULL; + count +------- + 0 +(1 row) + +SELECT * FROM Polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon + ORDER BY (poly_center(f1))[0]; +ERROR: relation "Polygon_tbl" does not exist on datanode1 +LINE 1: SELECT * FROM Polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::... + ^ +SELECT * FROM Circle_tbl WHERE f1 && circle(point(1,-2), 1) + ORDER BY area(f1); +ERROR: relation "Circle_tbl" does not exist on datanode1 +LINE 1: SELECT * FROM Circle_tbl WHERE f1 && circle(point(1,-2), 1) + ^ +--SELECT count(*) FROM gPolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; +--SELECT count(*) FROM gCircle_tbl WHERE f1 && '<(500,500),500>'::circle; +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; + count +------- + 3 +(1 row) + +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; + count +------- + 3 +(1 row) + +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; + count +------- + 3 +(1 row) + +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; + count +------- + 1 +(1 row) + +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; + count +------- + 3 +(1 row) + +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; + count +------- + 2 +(1 row) + +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; + count +------- + 1 +(1 row) + +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; + count +------- + 3 +(1 row) + +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; + count +------- + 1 +(1 row) + +SELECT * FROM point_tbl ORDER BY f1 <-> '0,1'; + f1 +------------ + (0,0) + (-3,4) + (-10,0) + (10,10) + (-5,-12) + (5.1,34.5) + +(7 rows) + +SELECT * FROM point_tbl WHERE f1 IS NULL; + f1 +---- + +(1 row) + +SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1'; + f1 +------------ + (0,0) + (-3,4) + (-10,0) + (10,10) + (-5,-12) + (5.1,34.5) +(6 rows) + +SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; + f1 +--------- + (0,0) + (-3,4) + (-10,0) + (10,10) +(4 rows) + +SELECT count(*) FROM Quad_point_tbl WHERE p IS NULL; + count +------- + 3 +(1 row) + +SELECT count(*) FROM Quad_point_tbl WHERE p IS NOT NULL; + count +------- + 1000 +(1 row) + +SELECT count(*) FROM Quad_point_tbl; + count +------- + 1003 +(1 row) + +SELECT count(*) FROM Quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; + count +------- + 1000 +(1 row) + +SELECT count(*) FROM Quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; + count +------- + 1000 +(1 row) + +SELECT count(*) FROM Quad_point_tbl WHERE p << '(5000, 4000)'; + count +------- + 1000 +(1 row) + +SELECT count(*) FROM Quad_point_tbl WHERE p >> '(5000, 4000)'; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Quad_point_tbl WHERE p <^ '(5000, 4000)'; + count +------- + 1000 +(1 row) + +SELECT count(*) FROM Quad_point_tbl WHERE p >^ '(5000, 4000)'; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Quad_point_tbl WHERE p ~= '(4585, 365)'; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdef'; + count +------- + 1000 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcde'; + count +------- + 1 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdefF'; + count +------- + 1 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t < 'Aztec Ct '; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<~ 'Aztec Ct '; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t <= 'Aztec Ct '; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<=~ 'Aztec Ct '; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Aztec Ct '; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Worth St '; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t >= 'Worth St '; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>=~ 'Worth St '; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t > 'Worth St '; + count +------- + 0 +(1 row) + +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>~ 'Worth St '; + count +------- + 0 +(1 row) + +-- Now check the results from plain indexscan +SET enable_seqscan = OFF; +SET enable_indexscan = ON; +SET enable_bitmapscan = OFF; +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Fast_emp4000 + WHERE home_base @ '(200,200),(2000,1000)'::box + ORDER BY (home_base[0])[0]; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT * FROM Fast_emp4000 + WHERE home_base @ '(200,200),(2000,1000)'::box + ORDER BY (home_base[0])[0]; + home_base +----------- +(0 rows) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Fast_emp4000 WHERE home_base IS NULL; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Fast_emp4000 WHERE home_base IS NULL; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon + ORDER BY (poly_center(f1))[0]; +ERROR: relation "Polygon_tbl" does not exist on datanode1 +LINE 2: SELECT * FROM Polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::... + ^ +SELECT * FROM Polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon + ORDER BY (poly_center(f1))[0]; +ERROR: relation "Polygon_tbl" does not exist on datanode1 +LINE 1: SELECT * FROM Polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::... + ^ +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Circle_tbl WHERE f1 && circle(point(1,-2), 1) + ORDER BY area(f1); +ERROR: relation "Circle_tbl" does not exist on datanode1 +LINE 2: SELECT * FROM Circle_tbl WHERE f1 && circle(point(1,-2), 1) + ^ +SELECT * FROM Circle_tbl WHERE f1 && circle(point(1,-2), 1) + ORDER BY area(f1); +ERROR: relation "Circle_tbl" does not exist on datanode1 +LINE 1: SELECT * FROM Circle_tbl WHERE f1 && circle(point(1,-2), 1) + ^ +--EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +--SELECT count(*) FROM gPolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; +--SELECT count(*) FROM gPolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; +--EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +--SELECT count(*) FROM gCircle_tbl WHERE f1 && '<(500,500),500>'::circle; +--SELECT count(*) FROM gCircle_tbl WHERE f1 && '<(500,500),500>'::circle; +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; + count +------- + 3 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; + count +------- + 3 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; + count +------- + 3 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; + count +------- + 1 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; + count +------- + 3 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; + count +------- + 2 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; + count +------- + 1 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; + count +------- + 3 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; + count +------- + 1 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM point_tbl ORDER BY f1 <-> '0,1'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT * FROM point_tbl ORDER BY f1 <-> '0,1'; + f1 +------------ + (0,0) + (-3,4) + (-10,0) + (10,10) + (-5,-12) + (5.1,34.5) + +(7 rows) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM point_tbl WHERE f1 IS NULL; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT * FROM point_tbl WHERE f1 IS NULL; + f1 +---- + +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1'; + f1 +------------ + (0,0) + (-3,4) + (-10,0) + (10,10) + (-5,-12) + (5.1,34.5) +(6 rows) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; + f1 +--------- + (0,0) + (-3,4) + (-10,0) + (10,10) +(4 rows) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p IS NULL; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p IS NULL; + count +------- + 3 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p IS NOT NULL; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p IS NOT NULL; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl; + count +------- + 1003 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p << '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p << '(5000, 4000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p >> '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p >> '(5000, 4000)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p <^ '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p <^ '(5000, 4000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p >^ '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p >^ '(5000, 4000)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p ~= '(4585, 365)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p ~= '(4585, 365)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p <@ box '(200,200,1000,1000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p <@ box '(200,200,1000,1000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE box '(200,200,1000,1000)' @> p; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE box '(200,200,1000,1000)' @> p; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p << '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p << '(5000, 4000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p >> '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p >> '(5000, 4000)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p <^ '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p <^ '(5000, 4000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p >^ '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p >^ '(5000, 4000)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p ~= '(4585, 365)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p ~= '(4585, 365)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdef'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdef'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcde'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcde'; + count +------- + 1 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdefF'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdefF'; + count +------- + 1 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t < 'Aztec Ct '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t < 'Aztec Ct '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<~ 'Aztec Ct '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<~ 'Aztec Ct '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t <= 'Aztec Ct '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t <= 'Aztec Ct '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<=~ 'Aztec Ct '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<=~ 'Aztec Ct '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Aztec Ct '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Aztec Ct '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Worth St '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Worth St '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t >= 'Worth St '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t >= 'Worth St '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>=~ 'Worth St '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>=~ 'Worth St '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t > 'Worth St '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t > 'Worth St '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>~ 'Worth St '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>~ 'Worth St '; + count +------- + 0 +(1 row) + +-- Now check the results from bitmap indexscan +SET enable_seqscan = OFF; +SET enable_indexscan = OFF; +SET enable_bitmapscan = ON; +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; + f1 +--------- + (0,0) + (-3,4) + (-10,0) + (10,10) +(4 rows) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p IS NULL; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p IS NULL; + count +------- + 3 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p IS NOT NULL; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p IS NOT NULL; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl; + count +------- + 1003 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p << '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p << '(5000, 4000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p >> '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p >> '(5000, 4000)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p <^ '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p <^ '(5000, 4000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p >^ '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p >^ '(5000, 4000)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p ~= '(4585, 365)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Quad_point_tbl WHERE p ~= '(4585, 365)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p <@ box '(200,200,1000,1000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p <@ box '(200,200,1000,1000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE box '(200,200,1000,1000)' @> p; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE box '(200,200,1000,1000)' @> p; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p << '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p << '(5000, 4000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p >> '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p >> '(5000, 4000)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p <^ '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p <^ '(5000, 4000)'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p >^ '(5000, 4000)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p >^ '(5000, 4000)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p ~= '(4585, 365)'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM KD_point_tbl WHERE p ~= '(4585, 365)'; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdef'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdef'; + count +------- + 1000 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcde'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcde'; + count +------- + 1 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdefF'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdefF'; + count +------- + 1 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t < 'Aztec Ct '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t < 'Aztec Ct '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<~ 'Aztec Ct '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<~ 'Aztec Ct '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t <= 'Aztec Ct '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t <= 'Aztec Ct '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<=~ 'Aztec Ct '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<=~ 'Aztec Ct '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Aztec Ct '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Aztec Ct '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Worth St '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Worth St '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t >= 'Worth St '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t >= 'Worth St '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>=~ 'Worth St '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>=~ 'Worth St '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t > 'Worth St '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t > 'Worth St '; + count +------- + 0 +(1 row) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>~ 'Worth St '; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>~ 'Worth St '; + count +------- + 0 +(1 row) + +RESET enable_seqscan; +RESET enable_indexscan; +RESET enable_bitmapscan; +-- +-- GIN over int[] and text[] +-- +-- Note: GIN currently supports only bitmap scans, not plain indexscans +-- +SET enable_seqscan = OFF; +SET enable_indexscan = OFF; +SET enable_bitmapscan = ON; +CREATE INDEX intarrayidx ON Array_index_op_test USING gin (i); +explain (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Array_index_op_test WHERE i @> '{32}' ORDER BY seqno; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT * FROM Array_index_op_test WHERE i @> '{32}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i && '{32}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i @> '{17}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i && '{17}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i @> '{32,17}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i && '{32,17}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i <@ '{38,34,32,89}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i = '{47,77}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i = '{}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i @> '{}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i && '{}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i <@ '{}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_op_test WHERE i = '{NULL}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_op_test WHERE i @> '{NULL}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_op_test WHERE i && '{NULL}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_op_test WHERE i <@ '{NULL}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +CREATE INDEX textarrayidx ON Array_index_op_test USING gin (t); +explain (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Array_index_op_test WHERE t @> '{AAAAAAAA72908}' ORDER BY seqno; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT * FROM Array_index_op_test WHERE t @> '{AAAAAAAA72908}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t && '{AAAAAAAA72908}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t @> '{AAAAAAAAAA646}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t && '{AAAAAAAAAA646}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t @> '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t && '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t <@ '{AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t = '{AAAAAAAAAA646,A87088}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t = '{}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t @> '{}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t && '{}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t <@ '{}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +-- And try it with a multicolumn GIN index +DROP INDEX intarrayidx, textarrayidx; +CREATE INDEX botharrayidx ON Array_index_op_test USING gin (i, t); +SELECT * FROM Array_index_op_test WHERE i @> '{32}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i && '{32}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t @> '{AAAAAAA80240}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t && '{AAAAAAA80240}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i @> '{32}' AND t && '{AAAAAAA80240}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE i && '{32}' AND t @> '{AAAAAAA80240}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_index_op_test WHERE t = '{}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_op_test WHERE i = '{NULL}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +SELECT * FROM Array_op_test WHERE i <@ '{NULL}' ORDER BY seqno; + seqno | i | t +-------+---+--- +(0 rows) + +RESET enable_seqscan; +RESET enable_indexscan; +RESET enable_bitmapscan; +-- +-- Test GIN index's reloptions +-- +CREATE INDEX gin_relopts_test ON Array_index_op_test USING gin (i) + WITH (FASTUPDATE=on, GIN_PENDING_LIST_LIMIT=128); +\d+ "gin_relopts_test" + Index "public.gin_relopts_test" + Column | Type | Definition | Storage +--------+---------+------------+--------- + i | integer | i | plain +gin, for table "public.Array_index_op_test" +Options: fastupdate=on, gin_pending_list_limit=128 + +-- +-- HASH +-- +CREATE INDEX hash_i4_index ON Hash_i4_heap USING hash (random int4_ops); +CREATE INDEX hash_name_index ON Hash_name_heap USING hash (random name_ops); +CREATE INDEX hash_txt_index ON Hash_txt_heap USING hash (random text_ops); +CREATE INDEX hash_f8_index ON Hash_f8_heap USING hash (random float8_ops); +-- CREATE INDEX hash_ovfl_index ON hash_ovfl_heap USING hash (x int4_ops); +-- +-- Test functional index +-- +-- PGXC: Here replication is used to ensure correct index creation +-- when a non-shippable expression is used. +-- PGXCTODO: this should be removed once global constraints are supported +CREATE TABLE func_index_heap (f1 text, f2 text) ; +CREATE UNIQUE INDEX func_index_index on func_index_heap (textcat(f1,f2)); +INSERT INTO func_index_heap VALUES('ABC','DEF'); +INSERT INTO func_index_heap VALUES('AB','CDEFG'); +INSERT INTO func_index_heap VALUES('QWE','RTY'); +-- this should fail because of unique index: +INSERT INTO func_index_heap VALUES('ABCD', 'EF'); +ERROR: duplicate key value violates unique constraint "func_index_index" +DETAIL: Key (textcat(f1, f2))=(ABCDEF) already exists. +-- but this shouldn't: +INSERT INTO func_index_heap VALUES('QWERTY'); +-- +-- Same test, expressional index +-- +DROP TABLE func_index_heap; +-- PGXC: Here replication is used to ensure correct index creation +-- when a non-shippable expression is used. +-- PGXCTODO: this should be removed once global constraints are supported +CREATE TABLE func_index_heap (f1 text, f2 text) ; +CREATE UNIQUE INDEX func_index_index on func_index_heap ((f1 || f2) text_ops); +INSERT INTO func_index_heap VALUES('ABC','DEF'); +INSERT INTO func_index_heap VALUES('AB','CDEFG'); +INSERT INTO func_index_heap VALUES('QWE','RTY'); +-- this should fail because of unique index: +INSERT INTO func_index_heap VALUES('ABCD', 'EF'); +ERROR: duplicate key value violates unique constraint "func_index_index" +DETAIL: Key ((f1 || f2))=(ABCDEF) already exists. +-- but this shouldn't: +INSERT INTO func_index_heap VALUES('QWERTY'); +-- +-- Also try building functional, expressional, and partial indexes on +-- tables that already contain data. +-- +create unique index hash_f8_index_1 on Hash_f8_heap(abs(random)); +create unique index hash_f8_index_2 on Hash_f8_heap((seqno + 1), random); +create unique index hash_f8_index_3 on Hash_f8_heap(random) where seqno > 1000; +-- +-- Try some concurrent index builds +-- +-- Unfortunately this only tests about half the code paths because there are +-- no concurrent updates happening to the table at the same time. +CREATE TABLE concur_heap (f1 text, f2 text); +-- empty table +CREATE INDEX CONCURRENTLY concur_index1 ON concur_heap(f2,f1); +INSERT INTO concur_heap VALUES ('a','b'); +INSERT INTO concur_heap VALUES ('b','b'); +-- unique index +CREATE UNIQUE INDEX CONCURRENTLY concur_index2 ON concur_heap(f1); +-- check if constraint is set up properly to be enforced +INSERT INTO concur_heap VALUES ('b','x'); +ERROR: duplicate key value violates unique constraint "concur_index2" +DETAIL: Key (f1)=(b) already exists. +-- check if constraint is enforced properly at build time +CREATE UNIQUE INDEX CONCURRENTLY concur_index3 ON concur_heap(f2); +ERROR: could not create unique index "concur_index3" +DETAIL: Key (f2)=(b) is duplicated. +-- test that expression indexes and partial indexes work concurrently +CREATE INDEX CONCURRENTLY concur_index4 on concur_heap(f2) WHERE f1='a'; +CREATE INDEX CONCURRENTLY concur_index5 on concur_heap(f2) WHERE f1='x'; +-- here we also check that you can default the index name +CREATE INDEX CONCURRENTLY on concur_heap((f2||f1)); +-- You can't do a concurrent index build in a transaction +START TRANSACTION; +CREATE INDEX CONCURRENTLY concur_index7 ON concur_heap(f1); +ERROR: CREATE INDEX CONCURRENTLY cannot run inside a transaction block +COMMIT; +-- But you can do a regular index build in a transaction +START TRANSACTION; +CREATE INDEX std_index on concur_heap(f2); +COMMIT; +-- check to make sure that the failed indexes were cleaned up properly and the +-- successful indexes are created properly. Notably that they do NOT have the +-- "invalid" flag set. +\d "concur_heap" +Table "public.concur_heap" + Column | Type | Modifiers +--------+------+----------- + f1 | text | + f2 | text | +Indexes: + "concur_index2" UNIQUE, btree (f1) TABLESPACE pg_default + "concur_index3" UNIQUE, btree (f2) TABLESPACE pg_default INVALID + "concur_heap_expr_idx" btree ((f2 || f1)) TABLESPACE pg_default + "concur_index1" btree (f2, f1) TABLESPACE pg_default + "concur_index4" btree (f2) TABLESPACE pg_default WHERE f1 = 'a'::text + "concur_index5" btree (f2) TABLESPACE pg_default WHERE f1 = 'x'::text + "std_index" btree (f2) TABLESPACE pg_default + +-- +-- Try some concurrent index drops +-- +DROP INDEX CONCURRENTLY "concur_index2"; -- works +DROP INDEX CONCURRENTLY IF EXISTS "concur_index2"; -- notice +NOTICE: index "concur_index2" does not exist, skipping +-- failures +DROP INDEX CONCURRENTLY "concur_index2", "concur_index3"; +ERROR: DROP INDEX CONCURRENTLY does not support dropping multiple objects +START TRANSACTION; +DROP INDEX CONCURRENTLY "concur_index5"; +ERROR: DROP INDEX CONCURRENTLY cannot run inside a transaction block +ROLLBACK; +-- successes +DROP INDEX CONCURRENTLY IF EXISTS "concur_index3"; +DROP INDEX CONCURRENTLY "concur_index4"; +DROP INDEX CONCURRENTLY "concur_index5"; +DROP INDEX CONCURRENTLY "concur_index1"; +DROP INDEX CONCURRENTLY "concur_heap_expr_idx"; +\d "concur_heap" +Table "public.concur_heap" + Column | Type | Modifiers +--------+------+----------- + f1 | text | + f2 | text | +Indexes: + "std_index" btree (f2) TABLESPACE pg_default + +DROP TABLE concur_heap; +-- +-- Test ADD CONSTRAINT USING INDEX +-- +CREATE TABLE cwi_test( a int , b varchar(10), c char); +-- add some data so that all tests have something to work with. +INSERT INTO cwi_test VALUES(1, 2), (3, 4), (5, 6); +CREATE UNIQUE INDEX cwi_uniq_idx ON cwi_test(a , b); +ALTER TABLE cwi_test ADD primary key USING INDEX cwi_uniq_idx; +\d "cwi_test" + Table "public.cwi_test" + Column | Type | Modifiers +--------+-----------------------+----------- + a | integer | not null + b | character varying(10) | not null + c | character(1) | +Indexes: + "cwi_uniq_idx" PRIMARY KEY, btree (a, b) TABLESPACE pg_default + +CREATE UNIQUE INDEX cwi_uniq2_idx ON cwi_test(b , a); +ALTER TABLE cwi_test DROP CONSTRAINT cwi_uniq_idx, + ADD CONSTRAINT cwi_replaced_pkey PRIMARY KEY + USING INDEX cwi_uniq2_idx; +NOTICE: ALTER TABLE / ADD CONSTRAINT USING INDEX will rename index "cwi_uniq2_idx" to "cwi_replaced_pkey" +\d "cwi_test" + Table "public.cwi_test" + Column | Type | Modifiers +--------+-----------------------+----------- + a | integer | not null + b | character varying(10) | not null + c | character(1) | +Indexes: + "cwi_replaced_pkey" PRIMARY KEY, btree (b, a) TABLESPACE pg_default + +DROP INDEX cwi_replaced_pkey; -- Should fail; a constraint depends on it +ERROR: cannot drop index cwi_replaced_pkey because constraint cwi_replaced_pkey on table cwi_test requires it +HINT: You can drop constraint cwi_replaced_pkey on table cwi_test instead. +DROP TABLE cwi_test; +-- +-- Tests for IS NULL/IS NOT NULL with b-tree indexes +-- +SELECT unique1, unique2 INTO onek_with_null FROM Onek; +INSERT INTO onek_with_null (unique1,unique2) VALUES (NULL, -1), (NULL, NULL); +CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2,unique1); +SET enable_seqscan = OFF; +SET enable_indexscan = ON; +SET enable_bitmapscan = ON; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; + count +------- + 2 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; + count +------- + 1 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; + count +------- + 0 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; + count +------- + 1 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; + count +------- + 0 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; + count +------- + 0 +(1 row) + +DROP INDEX onek_nulltest; +CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2 desc,unique1); +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; + count +------- + 2 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; + count +------- + 1 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; + count +------- + 0 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; + count +------- + 1 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; + count +------- + 0 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; + count +------- + 0 +(1 row) + +DROP INDEX onek_nulltest; +CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2 desc nulls last,unique1); +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; + count +------- + 2 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; + count +------- + 1 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; + count +------- + 0 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; + count +------- + 1 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; + count +------- + 0 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; + count +------- + 0 +(1 row) + +DROP INDEX onek_nulltest; +CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2 nulls first,unique1); +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; + count +------- + 2 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; + count +------- + 1 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; + count +------- + 0 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; + count +------- + 1 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; + count +------- + 0 +(1 row) + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; + count +------- + 0 +(1 row) + +DROP INDEX onek_nulltest; +-- Check initial-positioning logic too +CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2); +SET enable_seqscan = OFF; +SET enable_indexscan = ON; +SET enable_bitmapscan = OFF; +SELECT unique1, unique2 FROM onek_with_null + ORDER BY unique2 LIMIT 2; + unique1 | unique2 +---------+--------- + | -1 + | +(2 rows) + +SELECT unique1, unique2 FROM onek_with_null WHERE unique2 >= -1 + ORDER BY unique2 LIMIT 2; + unique1 | unique2 +---------+--------- + | -1 +(1 row) + +SELECT unique1, unique2 FROM onek_with_null WHERE unique2 >= 0 + ORDER BY unique2 LIMIT 2; + unique1 | unique2 +---------+--------- +(0 rows) + +SELECT unique1, unique2 FROM onek_with_null + ORDER BY unique2 DESC LIMIT 2; + unique1 | unique2 +---------+--------- + | + | -1 +(2 rows) + +SELECT unique1, unique2 FROM onek_with_null WHERE unique2 >= -1 + ORDER BY unique2 DESC LIMIT 2; + unique1 | unique2 +---------+--------- + | -1 +(1 row) + +SELECT unique1, unique2 FROM onek_with_null WHERE unique2 < 999 + ORDER BY unique2 DESC LIMIT 2; + unique1 | unique2 +---------+--------- + | -1 +(1 row) + +RESET enable_seqscan; +RESET enable_indexscan; +RESET enable_bitmapscan; +DROP TABLE onek_with_null; +-- +-- Check bitmap index path planning +-- +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42); +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT * FROM Tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42); + unique1 | unique2 | two | four | ten | twenty | hundred | thousand | twothousand | fivethous | tenthous | odd | even | stringu1 | stringu2 | string4 +---------+---------+-----+------+-----+--------+---------+----------+-------------+-----------+----------+-----+------+----------+----------+--------- +(0 rows) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM Tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); + count +------- + 0 +(1 row) + +-- +-- Check behavior with duplicate index column contents +-- +CREATE TABLE dupindexcols AS + SELECT unique1 as id, stringu2::text as f1 FROM Tenk1; +CREATE INDEX dupindexcols_i ON dupindexcols (f1, id, f1 text_pattern_ops); +ANALYZE dupindexcols; +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) + SELECT count(*) FROM dupindexcols + WHERE f1 > 'WA' and id < 1000 and f1 ~<~ 'YX'; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT count(*) FROM dupindexcols + WHERE f1 > 'WA' and id < 1000 and f1 ~<~ 'YX'; + count +------- + 0 +(1 row) + +-- +-- Check ordering of =ANY indexqual results (bug in 9.2.0) +-- +vacuum analyze Tenk1; -- ensure we get consistent plans here +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT unique1 FROM Tenk1 +WHERE unique1 IN (1,42,7) +ORDER BY unique1; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT unique1 FROM Tenk1 +WHERE unique1 IN (1,42,7) +ORDER BY unique1; + unique1 +--------- +(0 rows) + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT thousand, tenthous FROM Tenk1 +WHERE thousand < 2 AND tenthous IN (1001,3000) +ORDER BY thousand; +ERROR: unrecognized EXPLAIN option "num_nodes" +SELECT thousand, tenthous FROM Tenk1 +WHERE thousand < 2 AND tenthous IN (1001,3000) +ORDER BY thousand; + thousand | tenthous +----------+---------- +(0 rows) + +--test for relpages and reltuples of pg_class +create table test_table(a int, b int); +create table test_table_col(a int, b int) with (orientation=column); +insert into test_table select generate_series(1,100),generate_series(1,100); +insert into test_table_col select * from test_table; +analyze test_table; +analyze test_table_col; +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table'; + relpages | reltuples +----------+----------- + t | t +(1 row) + +create index test_table_idx1 on test_table(a,b); +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table'; + relpages | reltuples +----------+----------- + t | t +(1 row) + +analyze test_table; +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table_idx1'; + relpages | reltuples +----------+----------- + t | t +(1 row) + +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table_col'; + relpages | reltuples +----------+----------- + t | t +(1 row) + +create index test_table_col_idx1 on test_table_col(a,b); +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table_col'; + relpages | reltuples +----------+----------- + t | t +(1 row) + +analyze test_table_col; +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table_col_idx1'; + relpages | reltuples +----------+----------- + t | t +(1 row) + +--test nestloop index param path +create table t_hash_table (a int, b int); +create table t_rep_table (a int, b int) ; +create index idx_rep_table on t_rep_table(a); +explain (costs off) select /*+ rows(t_rep_table #100000) */ * from t_hash_table where t_hash_table.a in (select a from t_rep_table); + QUERY PLAN +---------------------------------------------------------- + Nested Loop Semi Join + -> Seq Scan on t_hash_table + -> Index Only Scan using idx_rep_table on t_rep_table + Index Cond: (a = t_hash_table.a) +(4 rows) + +explain (costs off) select /*+ rows(t_rep_table #100000) */ * from t_hash_table where '1' = '0' or t_hash_table.a in (select a from t_rep_table); + QUERY PLAN +---------------------------------------------------------- + Nested Loop Semi Join + -> Seq Scan on t_hash_table + -> Index Only Scan using idx_rep_table on t_rep_table + Index Cond: (a = t_hash_table.a) +(4 rows) + +create index test0 on t_rep_table(rownum); +ERROR: specified ROWNUM is not allowed here. +LINE 1: create index test0 on t_rep_table(rownum); + ^ +create index test0 on t_rep_table(sin(a), sin(rownum)); +ERROR: specified ROWNUM is not allowed here. +LINE 1: create index test0 on t_rep_table(sin(a), sin(rownum)); + ^ +create index test0 on t_rep_table(sin(a), sin(rownum+1)); +ERROR: specified ROWNUM is not allowed here. +LINE 1: create index test0 on t_rep_table(sin(a), sin(rownum+1)); + ^ +drop index idx_rep_table; +drop table t_hash_table; +drop table t_rep_table; +drop index test_table_idx1; +drop index test_table_col_idx1; +drop table test_table; +drop table test_table_col; diff --git a/contrib/dolphin/expected/case_sensitive_test/create_table.out b/contrib/dolphin/expected/case_sensitive_test/create_table.out new file mode 100644 index 0000000000000000000000000000000000000000..bcb30c8527cdc17c77be875dbc58828685870c92 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/create_table.out @@ -0,0 +1,495 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- CREATE_TABLE +-- +-- CREATE TABLE SYNTAX +-- +-- CLASS DEFINITIONS +-- +CREATE TABLE Src(a int) with(autovacuum_enabled = off); +insert into Src values(1); +CREATE TABLE Hobbies_r ( + name text, + person text +) with(autovacuum_enabled = off); +CREATE TABLE Equipment_r ( + name text, + hobby text +) with(autovacuum_enabled = off); +CREATE TABLE Onek ( + unique1 int4, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) with(autovacuum_enabled = off); +CREATE TABLE Onek2 AS SELECT * FROM Onek; +CREATE TABLE Tenk1 ( + unique1 int4, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) with(autovacuum_enabled = off); +CREATE TABLE Tenk2 ( + unique1 int4, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) with(autovacuum_enabled = off); +CREATE TABLE Person ( + name text, + age int4, + location point +); +CREATE TABLE Emp ( + name text, + age int4, + location point, + salary int4, + manager name +) with(autovacuum_enabled = off); +CREATE TABLE Student ( + name text, + age int4, + location point, + gpa float8 +); +CREATE TABLE Stud_Emp ( + name text, + age int4, + location point, + salary int4, + manager name, + gpa float8, + percent int4 +) with(autovacuum_enabled = off); +CREATE TABLE City ( + name name, + location box, + budget city_budget +) with(autovacuum_enabled = off); +ERROR: type "city_budget" does not exist +CREATE TABLE Dept ( + dname name, + mgrname text +) with(autovacuum_enabled = off); +CREATE TABLE Slow_emp4000 ( + home_base box +) with(autovacuum_enabled = off); +CREATE TABLE Fast_emp4000 ( + home_base box +) with(autovacuum_enabled = off); +CREATE TABLE Road ( + name text, + thepath path +); +CREATE TABLE iHighway( + name text, + thepath path +) with(autovacuum_enabled = off); +CREATE TABLE sHighway ( + surface text, + name text, + thepath path +) with(autovacuum_enabled = off); +CREATE TABLE Real_City ( + pop int4, + cname text, + outline path +) with(autovacuum_enabled = off); +-- +-- test the "star" operators a bit more thoroughly -- this time, +-- throw in lots of NULL fields... +-- +-- a is the type root +-- b and c Inherit from a (one-level single Inheritance) +-- d Inherits from b and c (two-level multiple Inheritance) +-- e Inherits from c (two-level single Inheritance) +-- f Inherits from e (three-level single Inheritance) +-- +CREATE TABLE a_Star ( + class char, + a int4 +) with(autovacuum_enabled = off); +CREATE TABLE b_Star ( + b text, + class char, + a int4 +) with(autovacuum_enabled = off); +CREATE TABLE c_Star ( + c name, + class char, + a int4 +) with(autovacuum_enabled = off); +CREATE TABLE d_Star ( + d float8, + b text, + class char, + a int4, + c name +) with(autovacuum_enabled = off); +CREATE TABLE e_Star ( + e int2, + c name, + class char, + a int4 +) with(autovacuum_enabled = off); +CREATE TABLE f_Star ( + f polygon, + e int2, + c name, + class char, + a int4 +) with(autovacuum_enabled = off); +CREATE TABLE AggTest ( + a int2, + b float4 +) with(autovacuum_enabled = off); +CREATE TABLE Hash_i4_heap ( + seqno int4, + random int4 +) with(autovacuum_enabled = off); +CREATE TABLE Hash_name_heap ( + seqno int4, + random name +) with(autovacuum_enabled = off); +CREATE TABLE Hash_txt_heap ( + seqno int4, + random text +) with(autovacuum_enabled = off); +-- PGXC: Here replication is used to ensure correct index creation +-- when a non-shippable expression is used. +-- PGXCTODO: this should be removed once global constraints are supported +CREATE TABLE Hash_f8_heap ( + seqno int4, + random float8 +) with(autovacuum_enabled = off); +-- don't include the hash_ovfl_heap stuff in the distribution +-- the data set is too large for what it's worth +-- +-- CREATE TABLE hash_ovfl_heap ( +-- x int4, +-- y int4 +-- ); +CREATE TABLE BT_i4_heap ( + seqno int4, + random int4 +) with(autovacuum_enabled = off); +CREATE TABLE BT_name_heap ( + seqno name, + random int4 +) with(autovacuum_enabled = off); +CREATE TABLE BT_txt_heap ( + seqno text, + random int4 +); +CREATE TABLE BT_f8_heap ( + seqno float8, + random int4 +) with(autovacuum_enabled = off); +CREATE TABLE Array_op_test ( + seqno int4, + i int4[], + t text[] +) with(autovacuum_enabled = off); +CREATE TABLE Array_index_op_test ( + seqno int4, + i int4[], + t text[] +) with(autovacuum_enabled = off); +CREATE TABLE IF NOT EXISTS Test_tsvector( + t text, + a tsvector +); +CREATE TABLE IF NOT EXISTS Test_tsvector( + t text +) with(autovacuum_enabled = off); +NOTICE: relation "Test_tsvector" already exists, skipping +CREATE UNLOGGED TABLE unlogged1 (a int primary key); -- OK +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "unlogged1_pkey" for table "unlogged1" +INSERT INTO unlogged1 VALUES (42); +CREATE UNLOGGED TABLE public.unlogged2 (a int primary key); -- also OK +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "unlogged2_pkey" for table "unlogged2" +CREATE UNLOGGED TABLE pg_temp.unlogged3 (a int primary key); -- not OK +ERROR: only temporary relations may be created in temporary schemas +CREATE TABLE pg_temp.implicitly_temp (a int primary key); -- OK +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "implicitly_temp_pkey" for table "implicitly_temp" +CREATE TEMP TABLE explicitly_temp (a int primary key); -- also OK +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "explicitly_temp_pkey" for table "explicitly_temp" +CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key); -- also OK +ERROR: temporary tables cannot specify a schema name +CREATE TEMP TABLE public.temp_to_perm (a int primary key); -- not OK +ERROR: temporary tables cannot specify a schema name +DROP TABLE unlogged1, public.unlogged2; +-- +-- CREATE TABLE AS TEST CASE: Expect the column typemod info is not lost on DN +-- +CREATE TABLE HW_create_as_test11(C_CHAR CHAR(102400)); +CREATE TABLE HW_create_as_test12(C_CHAR) as SELECT C_CHAR FROM HW_create_as_test11; +CREATE TABLE HW_create_as_test13 (C_CHAR CHAR(102400)); +ALTER TABLE HW_create_as_test13 InheRIT HW_create_as_test12; +DROP TABLE HW_create_as_test12; +ERROR: cannot drop table "HW_create_as_test12" because other objects depend on it +DETAIL: table "HW_create_as_test13" depends on table "HW_create_as_test12" +HINT: Use DROP ... CASCADE to drop the dependent objects too. +DROP TABLE HW_create_as_test13; +DROP TABLE HW_create_as_test11; +CREATE TABLE HW_create_as_test11(C_INT int); +CREATE TABLE HW_create_as_test12(C_INT) as SELECT C_INT FROM HW_create_as_test11; +ERROR: relation "HW_create_as_test12" already exists in schema "public" +DETAIL: creating new table with existing name in the same schema +CREATE TABLE HW_create_as_test13 (C_INT int); +ALTER TABLE HW_create_as_test13 InheRIT HW_create_as_test12; +ERROR: child table is missing column "c_char" +DROP TABLE HW_create_as_test13; +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test11; +CREATE TABLE HW_create_as_test11(COL1 numeric(10,2)); +CREATE TABLE HW_create_as_test12(COL1) as SELECT COL1 FROM HW_create_as_test11; +CREATE TABLE HW_create_as_test13 (COL1 numeric(10,2)); +ALTER TABLE HW_create_as_test13 InheRIT HW_create_as_test12; +DROP TABLE HW_create_as_test13; +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test11; +CREATE TABLE HW_create_as_test11(COL1 timestamp(1)); +CREATE TABLE HW_create_as_test12(COL1) as SELECT COL1 FROM HW_create_as_test11; +CREATE TABLE HW_create_as_test13 (COL1 timestamp(1)); +ALTER TABLE HW_create_as_test13 InheRIT HW_create_as_test12; +DROP TABLE HW_create_as_test13; +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test11; +CREATE TABLE HW_create_as_test11(COL1 int[2][2]); +CREATE TABLE HW_create_as_test12(COL1) as SELECT COL1 FROM HW_create_as_test11; +CREATE TABLE HW_create_as_test13 (COL1 int[2][2]); +ALTER TABLE HW_create_as_test13 InheRIT HW_create_as_test12; +DROP TABLE HW_create_as_test13; +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test11; +create table HW_create_as_test11(col1 int); +insert into HW_create_as_test11 values(1); +insert into HW_create_as_test11 values(2); +create table HW_create_as_test12 as select * from HW_create_as_test11 with no data; +select count(*) from HW_create_as_test12; + count +------- + 0 +(1 row) + +explain (analyze on, costs off) create table HW_create_as_test13 as select * from HW_create_as_test11 with no data; + QUERY PLAN +--------------------------------------------------------------- + Insert on "HW_create_as_test13" (Actual time: never executed) + -> Result (Actual time: never executed) + One-Time Filter: false +--?.* +(4 rows) + +drop table HW_create_as_test11; +drop table HW_create_as_test12; +drop table HW_create_as_test13; +CREATE TABLE HW_create_as_test11(COL1 int); +insert into HW_create_as_test11 values(1); +insert into HW_create_as_test11 values(2); +CREATE TABLE HW_create_as_test12 as SELECT '001' col1, COL1 col2 FROM HW_create_as_test11; +select * from HW_create_as_test12 order by 1, 2; + col1 | col2 +------+------ + 001 | 1 + 001 | 2 +(2 rows) + +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test11; +-- Zero column table is not supported any more. +CREATE TABLE Zero_column_table_test1(); +ERROR: must have at least one column +CREATE TABLE Zero_column_table_test2(); +ERROR: must have at least one column +CREATE TABLE Zero_column_table_test3(a INT); +ALTER TABLE Zero_column_table_test3 DROP COLUMN a; +ERROR: must have at least one column +DROP TABLE Zero_column_table_test3; +CREATE TABLE Zero_column_table_test6() with (orientation = column); +ERROR: must have at least one column +CREATE TABLE Zero_column_table_test7() with (orientation = column); +ERROR: must have at least one column +CREATE TABLE Zero_column_table_test8(a INT) with (orientation = column); +ALTER TABLE Zero_column_table_test8 DROP COLUMN a; +ERROR: must have at least one column +DROP TABLE Zero_column_table_test8; +--test create table of pg_node_tree type +create table PG_node_tree_tbl11(id int,name pg_node_tree); +ERROR: type pg_node_tree is not yet supported. +create table PG_node_tree_tbl12 as select * from pg_type; +ERROR: type pg_node_tree is not yet supported. +-- test unreserved keywords for table name +CREATE TABLE App(a int); +CREATE TABLE Movement(a int); +CREATE TABLE Pool(a int); +CREATE TABLE Profile(a int); +CREATE TABLE Resource(a int); +CREATE TABLE Store(a int); +CREATE TABLE Than(a int); +CREATE TABLE Workload(a int); +DROP TABLE App; +DROP TABLE Movement; +DROP TABLE Pool; +DROP TABLE Profile; +DROP TABLE Resource; +DROP TABLE Store; +DROP TABLE Than; +DROP TABLE Workload; +-- test orientation +CREATE TABLE Orientation_test_1 (c1 int) WITH (orientation = column); +CREATE TABLE Orientation_test_2 (c1 int) WITH (orientation = 'column'); +CREATE TABLE Orientation_test_3 (c1 int) WITH (orientation = "column"); +CREATE TABLE Orientation_test_4 (c1 int) WITH (orientation = row); +CREATE TABLE Orientation_test_5 (c1 int) WITH (orientation = 'row'); +CREATE TABLE Orientation_test_6 (c1 int) WITH (orientation = "row"); +DROP TABLE Orientation_test_1; +DROP TABLE Orientation_test_2; +DROP TABLE Orientation_test_3; +DROP TABLE Orientation_test_4; +DROP TABLE Orientation_test_5; +DROP TABLE Orientation_test_6; +CREATE SCHEMA "TEST"; +CREATE SCHEMA "SCHEMA_TEST"; +CREATE TABLE "SCHEMA_TEST"."Table" ( + column1 bigint, + column2 bigint +); +CREATE TABLE "TEST"."Test_Table"( + clm1 "SCHEMA_TEST"."Table", + clm2 bigint); + +select * from "TEST"."Test_Table"; + clm1 | clm2 +------+------ +(0 rows) + +set current_schema=information_schema; +create table Test_info(a int, b int); +insert into Test_info values(1,2),(2,3),(3,4),(4,5); +\d+ "Test_info" + Table "information_schema.Test_info" + Column | Type | Modifiers | Storage | Stats target | Description +--------+---------+-----------+---------+--------------+------------- + a | integer | | plain | | + b | integer | | plain | | +Has OIDs: no +Options: orientation=row, compression=no + +\d+ "sql_features" + Table "information_schema.sql_features" + Column | Type | Modifiers | Storage | Stats target | Description +------------------+----------------+-----------+----------+--------------+------------- + feature_id | character_data | | extended | | + feature_name | character_data | | extended | | + sub_feature_id | character_data | | extended | | + sub_feature_name | character_data | | extended | | + is_supported | yes_or_no | | extended | | + is_verified_by | character_data | | extended | | + comments | character_data | | extended | | +Has OIDs: no +Options: orientation=row, compression=no + +explain (verbose on, costs off) select count(*) from sql_features; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Aggregate + Output: count(*) + -> Seq Scan on information_schema.sql_features + Output: feature_id, feature_name, sub_feature_id, sub_feature_name, is_supported, is_verified_by, comments +(4 rows) + +select count(*) from sql_features; + count +------- + 672 +(1 row) + +explain (verbose on, costs off) select * from Test_info; + QUERY PLAN +-------------------------------------------- + Seq Scan on information_schema."Test_info" + Output: a, b +(2 rows) + +select count(*) from Test_info; + count +------- + 4 +(1 row) + +drop table Test_info; +reset current_schema; +create table t_Serial(a int, b serial); +NOTICE: CREATE TABLE will create implicit sequence "t_Serial_b_seq" for serial column "t_Serial.b" +create temp table t_Tmp(a int, b serial); +ERROR: It's not supported to create serial column on temporary table +create temp table t_Tmp(like t_Serial); +NOTICE: CREATE TABLE will create implicit sequence "t_Tmp_b_seq" for serial column "t_Tmp.b" +ERROR: Temporary sequences are not supported +set enable_beta_features = on; +create temp table t_Tmp(like t_Serial); +NOTICE: CREATE TABLE will create implicit sequence "t_Tmp_b_seq" for serial column "t_Tmp.b" +select nextval('"t_Tmp_b_seq"'); + nextval +--------- + 1 +(1 row) + +reset enable_beta_features; +set default_statistics_target = -50; +analyze t_Serial; +drop table t_Serial; +drop table t_Tmp; +-- schema.table +CREATE TABLE public.Test_indirection1(a int); +-- catalog.schema.table +CREATE TABLE table_name_test_db.public.Test_indirection2(a int); +-- error +CREATE TABLE unknown_obj.table_name_test_db.public.Test_indirection3(a int); +ERROR: improper qualified name (too many dotted names): unknown_obj.table_name_test_db.public.Test_indirection3 +LINE 1: CREATE TABLE unknown_obj.table_name_test_db.public.Test_indi... + ^ +drop table "TEST"."Test_Table"; +drop table "SCHEMA_TEST"."Table"; +drop schema "TEST"; +drop schema "SCHEMA_TEST"; diff --git a/contrib/dolphin/expected/case_sensitive_test/create_table_like.out b/contrib/dolphin/expected/case_sensitive_test/create_table_like.out new file mode 100644 index 0000000000000000000000000000000000000000..b7f75b4731ae09b3bfcce77131c7a26c0bbf527f --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/create_table_like.out @@ -0,0 +1,325 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +--FOR BLACKLIST FEATURE: SEQUENCE、EXCLUDE、InheRITS is not supported. +-- +/* Test Inheritance of structure (LIKE) */ +CREATE TABLE Inhx (xx text DEFAULT 'text'); +/* + * Test double Inheritance + * + * Ensure that defaults are NOT included unless + * INCLUDING DEFAULTS is specified + */ +CREATE TABLE Ctla (aa TEXT); +CREATE TABLE Ctlb (bb TEXT) InheRITS (Ctla); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +CREATE TABLE Foo (LIKE nonexistent); +ERROR: Table (null).nonexistent does not exist in current datanode. +LINE 1: CREATE TABLE Foo (LIKE nonexistent); + ^ +CREATE TABLE Inhe (ee text, LIKE Inhx) Inherits (Ctlb); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +INSERT INTO Inhe VALUES ('ee-col1', 'ee-col2', DEFAULT, 'ee-col4'); +ERROR: relation "Inhe" does not exist on datanode1 +LINE 1: INSERT INTO Inhe VALUES ('ee-col1', 'ee-col2', DEFAULT, 'ee-... + ^ +SELECT * FROM Inhe; /* Columns aa, bb, xx value NULL, ee */ +ERROR: relation "Inhe" does not exist on datanode1 +LINE 1: SELECT * FROM Inhe; + ^ +SELECT * FROM Inhx; /* Empty set since LIKE Inherits structure only */ + xx +---- +(0 rows) + +SELECT * FROM Ctlb; /* Has ee entry */ +ERROR: relation "Ctlb" does not exist on datanode1 +LINE 2: SELECT * FROM Ctlb; + ^ +SELECT * FROM Ctla; /* Has ee entry */ + aa +---- +(0 rows) + +CREATE TABLE inhf (LIKE Inhx, LIKE Inhx); /* Throw error */ +ERROR: column "xx" specified more than once +CREATE TABLE inhf (LIKE Inhx INCLUDING DEFAULTS INCLUDING CONSTRAINTS); +INSERT INTO inhf DEFAULT VALUES; +SELECT * FROM inhf; /* Single entry with value 'text' */ + xx +------ + text +(1 row) + +ALTER TABLE Inhx add constraint Foo CHECK (xx = 'text'); +ALTER TABLE Inhx ADD PRIMARY KEY (xx); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "Inhx_pkey" for table "Inhx" +CREATE TABLE Inhg (LIKE Inhx); /* Doesn't copy constraint */ +INSERT INTO Inhg VALUES ('foo'); +DROP TABLE Inhg; +CREATE TABLE Inhg (x text, LIKE Inhx INCLUDING CONSTRAINTS, y text); /* Copies constraints */ +INSERT INTO Inhg VALUES ('x', 'text', 'y'); /* Succeeds */ +INSERT INTO Inhg VALUES ('x', 'text', 'y'); /* Succeeds -- Unique constraints not copied */ +INSERT INTO Inhg VALUES ('x', 'foo', 'y'); /* fails due to constraint */ +ERROR: new row for relation "Inhg" violates check constraint "foo" +DETAIL: N/A +SELECT * FROM Inhg; /* Two records with three columns in order x=x, xx=text, y=y */ + x | xx | y +---+------+--- + x | text | y + x | text | y +(2 rows) + +DROP TABLE Inhg; +CREATE TABLE Inhg (x text, LIKE Inhx INCLUDING INDEXES, y text) DISTRIBUTE BY REPLICATION; /* copies indexes */ +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +INSERT INTO Inhg VALUES (5, 10); +ERROR: relation "Inhg" does not exist on datanode1 +LINE 2: INSERT INTO Inhg VALUES (5, 10); + ^ +INSERT INTO Inhg VALUES (20, 10); -- should fail +ERROR: relation "Inhg" does not exist on datanode1 +LINE 1: INSERT INTO Inhg VALUES (20, 10); + ^ +DROP TABLE Inhg; +ERROR: table "Inhg" does not exist +/* Multiple primary keys creation should fail */ +CREATE TABLE Inhg (x text, LIKE Inhx INCLUDING INDEXES, PRIMARY KEY(x)); /* fails */ +ERROR: multiple primary keys for table "Inhg" are not allowed +CREATE TABLE Inhz (xx text DEFAULT 'text', yy int UNIQUE) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE UNIQUE INDEX Inhz_xx_idx on Inhz (xx) WHERE xx <> 'Test'; +ERROR: relation "Inhz" does not exist +/* Ok to create multiple unique indexes */ +CREATE TABLE Inhg (x text UNIQUE, LIKE Inhz INCLUDING INDEXES) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +INSERT INTO Inhg (xx, yy, x) VALUES ('Test', 5, 10); +ERROR: relation "Inhg" does not exist on datanode1 +LINE 1: INSERT INTO Inhg (xx, yy, x) VALUES ('Test', 5, 10); + ^ +INSERT INTO Inhg (xx, yy, x) VALUES ('Test', 10, 15); +ERROR: relation "Inhg" does not exist on datanode1 +LINE 1: INSERT INTO Inhg (xx, yy, x) VALUES ('Test', 10, 15); + ^ +INSERT INTO Inhg (xx, yy, x) VALUES ('foo', 10, 15); -- should fail +ERROR: relation "Inhg" does not exist on datanode1 +LINE 1: INSERT INTO Inhg (xx, yy, x) VALUES ('foo', 10, 15); + ^ +DROP TABLE Inhg; +ERROR: table "Inhg" does not exist +DROP TABLE Inhz; +ERROR: table "Inhz" does not exist +-- including storage and comments +CREATE TABLE Ctlt1 (a text CHECK (length(a) > 2) PRIMARY KEY, b text); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Ctlt1_pkey" for table "Ctlt1" +CREATE INDEX ctlt1_b_key ON Ctlt1 (b); +CREATE INDEX ctlt1_fnidx ON Ctlt1 ((a || b)); +COMMENT ON COLUMN Ctlt1.a IS 'A'; +ERROR: relation "ctlt1" does not exist +COMMENT ON COLUMN Ctlt1.b IS 'B'; +ERROR: relation "ctlt1" does not exist +COMMENT ON CONSTRAINT ctlt1_a_check ON Ctlt1 IS 't1_a_check'; +ERROR: constraint "ctlt1_a_check" for table "Ctlt1" does not exist +COMMENT ON INDEX ctlt1_pkey IS 'index pkey'; +ERROR: relation "ctlt1_pkey" does not exist +COMMENT ON INDEX ctlt1_b_key IS 'index b_key'; +ALTER TABLE Ctlt1 ALTER COLUMN a SET STORAGE MAIN; +CREATE TABLE Ctlt2 (c text); +ALTER TABLE Ctlt2 ALTER COLUMN c SET STORAGE EXTERNAL; +COMMENT ON COLUMN Ctlt2.c IS 'C'; +ERROR: relation "ctlt2" does not exist +CREATE TABLE Ctlt3 (a text CHECK (length(a) < 5), c text); +ALTER TABLE Ctlt3 ALTER COLUMN c SET STORAGE EXTERNAL; +ALTER TABLE Ctlt3 ALTER COLUMN a SET STORAGE MAIN; +COMMENT ON COLUMN Ctlt3.a IS 'A3'; +ERROR: relation "ctlt3" does not exist +COMMENT ON COLUMN Ctlt3.c IS 'C'; +ERROR: relation "ctlt3" does not exist +COMMENT ON CONSTRAINT ctlt3_a_check ON Ctlt3 IS 't3_a_check'; +ERROR: constraint "ctlt3_a_check" for table "Ctlt3" does not exist +CREATE TABLE Ctlt4 (a text, c text); +ALTER TABLE Ctlt4 ALTER COLUMN c SET STORAGE EXTERNAL; +CREATE TABLE Ctlt12_storage (LIKE Ctlt1 INCLUDING STORAGE, LIKE Ctlt2 INCLUDING STORAGE); +\d+ "Ctlt12_storage" + Table "public.Ctlt12_storage" + Column | Type | Modifiers | Storage | Stats target | Description +--------+------+-----------+----------+--------------+------------- + a | text | not null | main | | + b | text | | extended | | + c | text | | external | | +Has OIDs: no +Options: orientation=row, compression=no + +CREATE TABLE Ctlt12_comments (LIKE Ctlt1 INCLUDING COMMENTS, LIKE Ctlt2 INCLUDING COMMENTS); +\d+ "Ctlt12_comments" + Table "public.Ctlt12_comments" + Column | Type | Modifiers | Storage | Stats target | Description +--------+------+-----------+----------+--------------+------------- + a | text | not null | extended | | + b | text | | extended | | + c | text | | extended | | +Has OIDs: no +Options: orientation=row, compression=no + +CREATE TABLE Ctlt1_inh (LIKE Ctlt1 INCLUDING CONSTRAINTS INCLUDING COMMENTS) InheRITS (Ctlt1); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +\d+ "Ctlt1_inh" +SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 'Ctlt1_inh'::regclass; +ERROR: relation "ctlt1_inh" does not exist +LINE 1: ...nt'::regclass AND objoid = c.oid AND c.conrelid = 'Ctlt1_inh... + ^ +CREATE TABLE Ctlt13_inh () InheRITS (Ctlt1, Ctlt3); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +\d+ "Ctlt13_inh" +CREATE TABLE ctlt13_like (LIKE Ctlt3 INCLUDING CONSTRAINTS INCLUDING COMMENTS INCLUDING STORAGE) InheRITS (Ctlt1); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +\d+ "ctlt13_like" +SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 'ctlt13_like'::regclass; +ERROR: relation "ctlt13_like" does not exist +LINE 1: ...nt'::regclass AND objoid = c.oid AND c.conrelid = 'ctlt13_li... + ^ +CREATE TABLE Ctlt_all (LIKE Ctlt1 INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Ctlt_all_pkey" for table "Ctlt_all" +\d+ "Ctlt_all" + Table "public.Ctlt_all" + Column | Type | Modifiers | Storage | Stats target | Description +--------+------+-----------+----------+--------------+------------- + a | text | not null | main | | + b | text | | extended | | +Indexes: + "Ctlt_all_pkey" PRIMARY KEY, btree (a) TABLESPACE pg_default + "Ctlt_all_b_idx" btree (b) TABLESPACE pg_default + "Ctlt_all_expr_idx" btree ((a || b)) TABLESPACE pg_default +Check constraints: + "Ctlt1_a_check" CHECK (length(a) > 2) +Has OIDs: no +Options: orientation=row, compression=no + +SELECT c.relname, objsubid, description FROM pg_description, pg_index i, pg_class c WHERE classoid = 'pg_class'::regclass AND objoid = i.indexrelid AND c.oid = i.indexrelid AND i.indrelid = 'Ctlt_all'::regclass ORDER BY c.relname, objsubid; +ERROR: relation "ctlt_all" does not exist +LINE 1: ...exrelid AND c.oid = i.indexrelid AND i.indrelid = 'Ctlt_all'... + ^ +CREATE TABLE Inh_error1 () InheRITS (Ctlt1, Ctlt4); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +CREATE TABLE Inh_error2 (LIKE Ctlt4 INCLUDING STORAGE) InheRITS (Ctlt1); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +DROP TABLE if exists Ctlt1, Ctlt2, Ctlt3, Ctlt4, Ctlt12_storage, Ctlt12_comments, Ctlt1_inh, Ctlt13_inh, ctlt13_like, Ctlt_all, Ctla, Ctlb CASCADE; +NOTICE: table "Ctlt1_inh" does not exist, skipping +NOTICE: table "Ctlt13_inh" does not exist, skipping +NOTICE: table "ctlt13_like" does not exist, skipping +NOTICE: table "Ctlb" does not exist, skipping +/* LIKE with other relation kinds */ +CREATE TABLE Ctlt4 (a int, b text); +CREATE SEQUENCE ctlseq1; +CREATE TABLE ctlt10 (LIKE ctlseq1); -- fail +ERROR: "ctlseq1" is not a table, view, composite type, or foreign table +LINE 1: CREATE TABLE ctlt10 (LIKE ctlseq1); + ^ +CREATE VIEW ctlv1 AS SELECT * FROM Ctlt4; +CREATE TABLE Ctlt11 (LIKE ctlv1); +ERROR: openGauss does not support VIEW in LIKE clauses +DETAIL: The feature is not currently supported +CREATE TABLE ctlt11a (LIKE ctlv1 INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS); +ERROR: openGauss does not support VIEW in LIKE clauses +DETAIL: The feature is not currently supported +CREATE TYPE ctlty1 AS (a int, b text); +CREATE TABLE Ctlt12 (LIKE ctlty1); +-- including all, including all excluding some option(s) +CREATE TABLE Ctlt13 (LIKE Ctlt4 INCLUDING ALL); +CREATE TABLE Ctlt14 (LIKE Ctlt4 INCLUDING ALL EXCLUDING RELOPTIONS) WITH (ORIENTATION = COLUMN); +-- should fail, syntax error +CREATE TABLE Ctlt15 (LIKE Ctlt4 INCLUDING ALL INCLUDING RELOPTIONS); +ERROR: syntax error at or near "INCLUDING RELOPTIONS" +LINE 1: CREATE TABLE Ctlt15 (LIKE Ctlt4 INCLUDING ALL INCLUDING RELO... + ^ +CREATE TABLE Ctlt16 (LIKE Ctlt4 INCLUDING ALL EXCLUDING ALL); +CREATE TABLE Ctlt17 (LIKE Ctlt4 INCLUDING DEFAULTS INCLUDING CONSTRAINTS EXCLUDING ALL); +CREATE TABLE Ctlt18 (LIKE Ctlt4 EXCLUDING ALL); +DROP SEQUENCE ctlseq1; +DROP TYPE ctlty1; +DROP VIEW ctlv1; +DROP TABLE IF EXISTS Ctlt4, ctlt10, Ctlt11, ctlt11a, Ctlt12, Ctlt13, Ctlt14, Ctlt16, Ctlt17, Ctlt18; +NOTICE: table "ctlt10" does not exist, skipping +NOTICE: table "Ctlt11" does not exist, skipping +NOTICE: table "ctlt11a" does not exist, skipping +create table Ctltcol(id1 integer, id2 integer, id3 integer, partial cluster key(id1,id2))with(orientation = column); +create table Ctltcollike(like Ctltcol including all); +\d+ "Ctltcollike" + Table "public.Ctltcollike" + Column | Type | Modifiers | Storage | Stats target | Description +--------+---------+-----------+---------+--------------+------------- + id1 | integer | | plain | | + id2 | integer | | plain | | + id3 | integer | | plain | | +Partial Cluster : + "Ctltcollike_cluster" PARTIAL CLUSTER KEY (id1, id2) +Has OIDs: no +Options: orientation=column, compression=low + +drop table Ctltcol; +drop table Ctltcollike; +create table Test1(a int, b int, c int)distribute by hash(a, b); +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +create table Test (like Test1 including distribution); +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +\d+ "Test" +drop table Test; +ERROR: table "Test" does not exist +drop table Test1; +ERROR: table "Test1" does not exist +-- including all, with oids /without oids +create table Ctltesta(a1 int, a2 int) with oids; +ERROR: CREATE TABLE ... WITH OIDS is not yet supported. +\d+ "Ctltesta" +create table Ctltestb(like Ctltesta including all); +ERROR: Table (null).Ctltesta does not exist in current datanode. +LINE 1: create table Ctltestb(like Ctltesta including all); + ^ +\d+ "Ctltestb" +create table Ctltestc(like Ctltesta including all excluding oids); +ERROR: Table (null).Ctltesta does not exist in current datanode. +LINE 1: create table Ctltestc(like Ctltesta including all excluding ... + ^ +\d+ "Ctltestc" +create table Ctltestd(a1 int, a2 int, constraint firstkey primary key(a1))with oids distribute by hash(a1); +ERROR: CREATE TABLE ... WITH OIDS is not yet supported. +\d+ "Ctltestd" +create table Ctlteste(like Ctltestd including all); +ERROR: Table (null).Ctltestd does not exist in current datanode. +LINE 1: create table Ctlteste(like Ctltestd including all); + ^ +\d+ "Ctlteste" +drop table if exists Ctltesta, Ctltestb, Ctltestc,Ctltestd, Ctlteste; +NOTICE: table "Ctltesta" does not exist, skipping +NOTICE: table "Ctltestb" does not exist, skipping +NOTICE: table "Ctltestc" does not exist, skipping +NOTICE: table "Ctltestd" does not exist, skipping +NOTICE: table "Ctlteste" does not exist, skipping +create table Ctltestf(a1 int, a2 int, constraint firstkey primary key(oid)) distribute by hash(a1); +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +\d+ "Ctltestf" +create table Ctltestg(a1 int, a2 int, constraint firstkey primary key(oid))with oids distribute by hash(a1); +ERROR: CREATE TABLE ... WITH OIDS is not yet supported. +\d+ "Ctltestg" +drop table if exists Ctltestf, Ctltestg; +NOTICE: table "Ctltestf" does not exist, skipping +NOTICE: table "Ctltestg" does not exist, skipping +create schema testschema; +CREATE OR REPLACE FUNCTION testschema.func_increment_plsql(i integer) RETURNS integer AS $$ + BEGIN + RETURN i + 1; + END; +$$ LANGUAGE plpgsql IMMUTABLE ; +create table testschema.Test1 (a int , b int default testschema.func_increment_plsql(1)); +alter schema testschema rename to TESTTABLE_bak; +create table TESTTABLE_bak.Test2 (like TESTTABLE_bak.Test1 including all); +drop table TESTTABLE_bak.Test2; +drop table TESTTABLE_bak.Test1; +drop function TESTTABLE_bak.func_increment_plsql(); diff --git a/contrib/dolphin/expected/case_sensitive_test/delete.out b/contrib/dolphin/expected/case_sensitive_test/delete.out new file mode 100644 index 0000000000000000000000000000000000000000..4e689887f1e5c4154ad3ec04a86886bb54f98c1f --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/delete.out @@ -0,0 +1,39 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +CREATE TABLE Delete_test ( + id int PRIMARY KEY, + a INT, + b text +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Delete_test_pkey" for table "Delete_test" +INSERT INTO Delete_test (a) VALUES (10); +ERROR: null value in column "id" violates not-null constraint +DETAIL: Failing row contains (null, 10, null). +INSERT INTO Delete_test (a, b) VALUES (50, repeat('x', 10000)); +ERROR: null value in column "id" violates not-null constraint +DETAIL: Failing row contains (null, 50, xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...). +INSERT INTO Delete_test (a) VALUES (100); +ERROR: null value in column "id" violates not-null constraint +DETAIL: Failing row contains (null, 100, null). +-- allow an alias to be specified for DELETE's target table +DELETE FROM Delete_test AS dt WHERE dt.a > 75; +-- if an alias is specified, don't allow the original table name +-- to be referenced +DELETE FROM Delete_test dt WHERE Delete_test.a > 25; +ERROR: invalid reference to FROM-clause entry for table "Delete_test" +LINE 1: DELETE FROM Delete_test dt WHERE Delete_test.a > 25; + ^ +HINT: Perhaps you meant to reference the table alias "dt". +SELECT id, a, char_length(b) FROM Delete_test ORDER BY id; + id | a | char_length +----+---+------------- +(0 rows) + +-- delete a row with a TOASTed value +DELETE FROM Delete_test WHERE a > 25; +SELECT id, a, char_length(b) FROM Delete_test ORDER BY id; + id | a | char_length +----+---+------------- +(0 rows) + +DROP TABLE Delete_test; diff --git a/contrib/dolphin/expected/case_sensitive_test/drop.out b/contrib/dolphin/expected/case_sensitive_test/drop.out new file mode 100644 index 0000000000000000000000000000000000000000..9eb5edb86d9c3fb1ddc78b1bf57cb32c6599a5dc --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/drop.out @@ -0,0 +1,151 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- drop.source +-- +-- +-- this will fail if the user is not the postgres superuser. +-- if it does, don't worry about it (you can turn usersuper +-- back on as "postgres"). too many people don't follow +-- directions and run this as "postgres", though... +-- +UPDATE pg_user + SET usesuper = 't'::bool + WHERE usename = 'postgres'; +ERROR: cannot update view "pg_user" +HINT: You need an unconditional ON UPDATE DO INSTEAD rule or an INSTEAD OF UPDATE trigger. +-- +-- FUNCTION REMOVAL +-- +DROP FUNCTION hobbies("Person"); +ERROR: function hobbies("Person") does not exist +DROP FUNCTION hobby_construct(text,text); +ERROR: function hobby_construct(text, text) does not exist +DROP FUNCTION equipment("Hobbies_r"); +ERROR: function equipment("Hobbies_r") does not exist +DROP FUNCTION user_relns(); +ERROR: function user_relns does not exist +DROP FUNCTION widget_in(cstring); +ERROR: function widget_in(cstring) does not exist +DROP FUNCTION widget_out(widget); +ERROR: type "widget" does not exist +DROP FUNCTION pt_in_widget(point,widget); +ERROR: type "widget" does not exist +DROP FUNCTION overpaid(Emp); +ERROR: type "emp" does not exist +DROP FUNCTION boxarea(box); +ERROR: function boxarea(box) does not exist +DROP FUNCTION interpt_pp(path,path); +ERROR: function interpt_pp(path, path) does not exist +DROP FUNCTION reverse_name(name); +ERROR: function reverse_name(name) does not exist +DROP FUNCTION oldstyle_length(int4, text); +ERROR: function oldstyle_length(integer, text) does not exist +-- +-- OPERATOR REMOVAL +-- +DROP OPERATOR ## (path, path); +ERROR: operator does not exist: path ## path +DROP OPERATOR <% (point, widget); +ERROR: type "widget" does not exist +-- left unary +DROP OPERATOR @#@ (none, int4); +ERROR: operator does not exist: @#@ integer +-- right unary +DROP OPERATOR #@# (int4, none); +ERROR: operator does not exist: integer #@# +-- right unary +DROP OPERATOR #%# (int4, none); +ERROR: operator does not exist: integer #%# +-- +-- ABSTRACT DATA TYPE REMOVAL +-- +DROP TYPE city_budget; +ERROR: type "city_budget" does not exist +DROP TYPE widget; +ERROR: type "widget" does not exist +-- +-- RULE REMOVAL +-- (is also tested in queries.source) +-- +-- +-- AGGREGATE REMOVAL +-- +DROP AGGREGATE newavg (int4); +ERROR: aggregate newavg(integer) does not exist +DROP AGGREGATE newsum (int4); +ERROR: aggregate newsum(integer) does not exist +DROP AGGREGATE newcnt (int4); +ERROR: aggregate newcnt(integer) does not exist +-- +-- CLASS REMOVAL +-- (Inheritance hierarchies are deleted in reverse order) +-- +-- +-- DROP ancillary data structures (i.e. indices) +-- +DROP INDEX onek_unique1; +DROP INDEX onek_unique2; +DROP INDEX onek_hundred; +DROP INDEX onek_stringu1; +DROP INDEX tenk1_unique1; +DROP INDEX tenk1_unique2; +DROP INDEX tenk1_hundred; +DROP INDEX tenk2_unique1; +DROP INDEX tenk2_unique2; +DROP INDEX tenk2_hundred; +-- DROP INDEX onek2_u1_prtl; +-- DROP INDEX onek2_u2_prtl; +-- DROP INDEX onek2_stu1_prtl; +DROP INDEX rix; +DROP INDEX iix; +DROP INDEX six; +DROP INDEX hash_i4_index; +DROP INDEX hash_name_index; +DROP INDEX hash_txt_index; +DROP INDEX hash_f8_index; +-- DROP INDEX hash_ovfl_index; +DROP INDEX bt_i4_index; +DROP INDEX bt_name_index; +DROP INDEX bt_txt_index; +DROP INDEX bt_f8_index; +DROP TABLE Onek; +DROP TABLE Onek2; +DROP TABLE Tenk1; +DROP TABLE Tenk2; +DROP TABLE Hobbies_r; +DROP TABLE Equipment_r; +DROP TABLE AggTest; +DROP TABLE f_Star; +DROP TABLE e_Star; +DROP TABLE d_Star; +DROP TABLE c_Star; +DROP TABLE b_Star; +DROP TABLE a_Star; +-- +-- must be in reverse Inheritance order +-- +DROP TABLE Stud_Emp; +DROP TABLE Student; +DROP TABLE Slow_emp4000; +DROP TABLE Fast_emp4000; +DROP TABLE Emp; +DROP TABLE Person; +DROP TABLE ramp; +ERROR: table "ramp" does not exist +DROP TABLE Real_City; +DROP TABLE Dept; +DROP TABLE iHighway; +DROP TABLE sHighway; +DROP TABLE Road; +DROP TABLE City; +ERROR: table "City" does not exist +DROP TABLE Hash_i4_heap; +DROP TABLE Hash_name_heap; +DROP TABLE Hash_txt_heap; +DROP TABLE Hash_f8_heap; +-- DROP TABLE hash_ovfl_heap; +DROP TABLE BT_i4_heap; +DROP TABLE BT_name_heap; +DROP TABLE BT_txt_heap; +DROP TABLE BT_f8_heap; diff --git a/contrib/dolphin/expected/case_sensitive_test/foreign_key.out b/contrib/dolphin/expected/case_sensitive_test/foreign_key.out new file mode 100644 index 0000000000000000000000000000000000000000..825aa37731eee48af20e1c2e34fab91f532ff028 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/foreign_key.out @@ -0,0 +1,1609 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- FOREIGN KEY +-- +-- MATCH FULL +-- +-- First test, check and cascade +-- +CREATE TABLE PKTABLE ( ptest1 int PRIMARY KEY, ptest2 text ) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE FKTABLE ( ftest1 int REFERENCES PKTABLE MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE, ftest2 int ) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 'Test1'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 'Test1'); + ^ +INSERT INTO PKTABLE VALUES (2, 'Test2'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (2, 'Test2'); + ^ +INSERT INTO PKTABLE VALUES (3, 'Test3'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (3, 'Test3'); + ^ +INSERT INTO PKTABLE VALUES (4, 'Test4'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (4, 'Test4'); + ^ +INSERT INTO PKTABLE VALUES (5, 'Test5'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (5, 'Test5'); + ^ +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, 2); + ^ +INSERT INTO FKTABLE VALUES (2, 3); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (2, 3); + ^ +INSERT INTO FKTABLE VALUES (3, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (3, 4); + ^ +INSERT INTO FKTABLE VALUES (NULL, 1); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 1); + ^ +-- Insert a failed row into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (100, 2); + ^ +-- Check FKTABLE +SELECT * FROM FKTABLE ORDER BY 1, 2; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2; + ^ +-- Delete a row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=1; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE WHERE ptest1=1; + ^ +-- Check FKTABLE for removal of matched row +SELECT * FROM FKTABLE ORDER BY 1, 2; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2; + ^ +-- Update a row from PK TABLE +UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; + ^ +-- Check FKTABLE for update of matched row +SELECT * FROM FKTABLE ORDER BY 1, 2; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2; + ^ +DROP TABLE FKTABLE; +ERROR: table "FKTABLE" does not exist +DROP TABLE PKTABLE; +ERROR: table "PKTABLE" does not exist +-- +-- check set NULL and table constraint on multiple columns +-- +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 text, PRIMARY KEY(ptest1, ptest2) ) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, CONSTRAINT constrname FOREIGN KEY(ftest1, ftest2) + REFERENCES PKTABLE MATCH FULL ON DELETE SET NULL ON UPDATE SET NULL) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- Test comments +COMMENT ON CONSTRAINT constrname_wrong ON FKTABLE IS 'fk constraint comment'; +ERROR: relation "fktable" does not exist +COMMENT ON CONSTRAINT constrname ON FKTABLE IS 'fk constraint comment'; +ERROR: relation "fktable" does not exist +COMMENT ON CONSTRAINT constrname ON FKTABLE IS NULL; +ERROR: relation "fktable" does not exist +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 2, 'Test1'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 2, 'Test1'); + ^ +INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2'); + ^ +INSERT INTO PKTABLE VALUES (2, 4, 'Test2'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (2, 4, 'Test2'); + ^ +INSERT INTO PKTABLE VALUES (3, 6, 'Test3'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (3, 6, 'Test3'); + ^ +INSERT INTO PKTABLE VALUES (4, 8, 'Test4'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (4, 8, 'Test4'); + ^ +INSERT INTO PKTABLE VALUES (5, 10, 'Test5'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (5, 10, 'Test5'); + ^ +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, 2, 4); + ^ +INSERT INTO FKTABLE VALUES (1, 3, 5); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, 3, 5); + ^ +INSERT INTO FKTABLE VALUES (2, 4, 8); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (2, 4, 8); + ^ +INSERT INTO FKTABLE VALUES (3, 6, 12); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (3, 6, 12); + ^ +INSERT INTO FKTABLE VALUES (NULL, NULL, 0); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, NULL, 0); + ^ +-- Insert failed rows into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (100, 2, 4); + ^ +INSERT INTO FKTABLE VALUES (2, 2, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (2, 2, 4); + ^ +INSERT INTO FKTABLE VALUES (NULL, 2, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 2, 4); + ^ +INSERT INTO FKTABLE VALUES (1, NULL, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, NULL, 4); + ^ +-- Check FKTABLE +SELECT * FROM FKTABLE ORDER BY 1, 2, 3; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2, 3; + ^ +-- Delete a row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=1 and ptest2=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE WHERE ptest1=1 and ptest2=2; + ^ +-- Check FKTABLE for removal of matched row +SELECT * FROM FKTABLE ORDER BY 1, 2, 3; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2, 3; + ^ +-- Delete another row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=5 and ptest2=10; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE WHERE ptest1=5 and ptest2=10; + ^ +-- Check FKTABLE (should be no change) +SELECT * FROM FKTABLE ORDER BY 1, 2, 3; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2, 3; + ^ +-- Update a row from PK TABLE +UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; + ^ +-- Check FKTABLE for update of matched row +SELECT * FROM FKTABLE ORDER BY 1, 2, 3; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2, 3; + ^ +-- Try altering the column type where foreign keys are involved +ALTER TABLE PKTABLE ALTER COLUMN ptest1 TYPE bigint; +ERROR: relation "PKTABLE" does not exist +ALTER TABLE FKTABLE ALTER COLUMN ftest1 TYPE bigint; +ERROR: relation "FKTABLE" does not exist +SELECT * FROM PKTABLE ORDER BY 1, 2, 3; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM PKTABLE ORDER BY 1, 2, 3; + ^ +SELECT * FROM FKTABLE ORDER BY 1, 2, 3; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2, 3; + ^ +DROP TABLE PKTABLE CASCADE; +ERROR: table "PKTABLE" does not exist +DROP TABLE FKTABLE; +ERROR: table "FKTABLE" does not exist +-- +-- check set default and table constraint on multiple columns +-- +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 text, PRIMARY KEY(ptest1, ptest2) ) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE FKTABLE ( ftest1 int DEFAULT -1, ftest2 int DEFAULT -2, ftest3 int, CONSTRAINT constrname2 FOREIGN KEY(ftest1, ftest2) + REFERENCES PKTABLE MATCH FULL ON DELETE SET DEFAULT ON UPDATE SET DEFAULT); +ERROR: relation "PKTABLE" does not exist +-- Insert a value in PKTABLE for default +INSERT INTO PKTABLE VALUES (-1, -2, 'The Default!'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (-1, -2, 'The Default!'); + ^ +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 2, 'Test1'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 2, 'Test1'); + ^ +INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2'); + ^ +INSERT INTO PKTABLE VALUES (2, 4, 'Test2'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (2, 4, 'Test2'); + ^ +INSERT INTO PKTABLE VALUES (3, 6, 'Test3'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (3, 6, 'Test3'); + ^ +INSERT INTO PKTABLE VALUES (4, 8, 'Test4'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (4, 8, 'Test4'); + ^ +INSERT INTO PKTABLE VALUES (5, 10, 'Test5'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (5, 10, 'Test5'); + ^ +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, 2, 4); + ^ +INSERT INTO FKTABLE VALUES (1, 3, 5); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, 3, 5); + ^ +INSERT INTO FKTABLE VALUES (2, 4, 8); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (2, 4, 8); + ^ +INSERT INTO FKTABLE VALUES (3, 6, 12); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (3, 6, 12); + ^ +INSERT INTO FKTABLE VALUES (NULL, NULL, 0); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, NULL, 0); + ^ +-- Insert failed rows into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (100, 2, 4); + ^ +INSERT INTO FKTABLE VALUES (2, 2, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (2, 2, 4); + ^ +INSERT INTO FKTABLE VALUES (NULL, 2, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 2, 4); + ^ +INSERT INTO FKTABLE VALUES (1, NULL, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, NULL, 4); + ^ +-- Check FKTABLE +SELECT * FROM FKTABLE ORDER BY 1, 2, 3; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2, 3; + ^ +-- Delete a row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=1 and ptest2=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE WHERE ptest1=1 and ptest2=2; + ^ +-- Check FKTABLE to check for removal +SELECT * FROM FKTABLE ORDER BY 1, 2, 3; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2, 3; + ^ +-- Delete another row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=5 and ptest2=10; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE WHERE ptest1=5 and ptest2=10; + ^ +-- Check FKTABLE (should be no change) +SELECT * FROM FKTABLE ORDER BY 1, 2, 3; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2, 3; + ^ +-- Update a row from PK TABLE +UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; + ^ +-- Check FKTABLE for update of matched row +SELECT * FROM FKTABLE ORDER BY 1, 2, 3; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * FROM FKTABLE ORDER BY 1, 2, 3; + ^ +-- this should fail for lack of CASCADE +DROP TABLE PKTABLE; +ERROR: table "PKTABLE" does not exist +DROP TABLE PKTABLE CASCADE; +ERROR: table "PKTABLE" does not exist +DROP TABLE FKTABLE; +ERROR: table "FKTABLE" does not exist +-- +-- First test, check with no on delete or on update +-- +CREATE TABLE PKTABLE ( ptest1 int PRIMARY KEY, ptest2 text ) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE FKTABLE ( ftest1 int REFERENCES PKTABLE MATCH FULL, ftest2 int ) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 'Test1'); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO PKTABLE VALUES (1, 'Test1'); + ^ +INSERT INTO PKTABLE VALUES (2, 'Test2'); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO PKTABLE VALUES (2, 'Test2'); + ^ +INSERT INTO PKTABLE VALUES (3, 'Test3'); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO PKTABLE VALUES (3, 'Test3'); + ^ +INSERT INTO PKTABLE VALUES (4, 'Test4'); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO PKTABLE VALUES (4, 'Test4'); + ^ +INSERT INTO PKTABLE VALUES (5, 'Test5'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (5, 'Test5'); + ^ +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO FKTABLE VALUES (1, 2); + ^ +INSERT INTO FKTABLE VALUES (2, 3); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (2, 3); + ^ +INSERT INTO FKTABLE VALUES (3, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (3, 4); + ^ +INSERT INTO FKTABLE VALUES (NULL, 1); +ERROR: timestamp out of range +CONTEXT: referenced column: ftest2 +-- Insert a failed row into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (100, 2); + ^ +-- Check FKTABLE +SELECT * FROM FKTABLE ORDER BY 1, 2; + ftest1 | ftest2 +--------+-------- +(0 rows) + +-- Check PKTABLE +SELECT * FROM PKTABLE ORDER BY 1, 2; + ptest1 | ptest2 +--------+-------- +(0 rows) + +-- Delete a row from PK TABLE (should fail) +DELETE FROM PKTABLE WHERE ptest1=1; +-- Delete a row from PK TABLE (should succeed) +DELETE FROM PKTABLE WHERE ptest1=5; +-- Check PKTABLE for deletes +SELECT * FROM PKTABLE ORDER BY 1, 2; + ptest1 | ptest2 +--------+-------- +(0 rows) + +-- Update a row from PK TABLE (should fail) +UPDATE PKTABLE SET ptest1=0 WHERE ptest1=2; +-- Update a row from PK TABLE (should succeed) +UPDATE PKTABLE SET ptest1=0 WHERE ptest1=4; +-- Check PKTABLE for updates +SELECT * FROM PKTABLE ORDER BY 1, 2; + ptest1 | ptest2 +--------+-------- +(0 rows) + +DROP TABLE FKTABLE; +ERROR: table "FKTABLE" does not exist +DROP TABLE PKTABLE; +-- MATCH unspecified +-- Base test restricting update/delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); + ^ +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); + ^ +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); + ^ +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); + ^ +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO FKTABLE VALUES (1, 2, 3, 1); + ^ +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); + ^ +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); + ^ +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); + ^ +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); + ^ +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); +ERROR: INSERT has more expressions than target columns +LINE 1: INSERT INTO FKTABLE VALUES (1, 2, 7, 6); + ^ +-- Show FKTABLE +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; +ERROR: ORDER BY position 3 is not in select list +LINE 1: SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ^ +-- Try to update something that should fail +UPDATE PKTABLE set ptest2=5 where ptest2=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE set ptest2=5 where ptest2=2; + ^ +-- Try to update something that should succeed +UPDATE PKTABLE set ptest1=1 WHERE ptest2=3; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE set ptest1=1 WHERE ptest2=3; + ^ +-- Try to delete something that should fail +DELETE FROM PKTABLE where ptest1=1 and ptest2=2 and ptest3=3; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE where ptest1=1 and ptest2=2 and ptest3=3... + ^ +-- Try to delete something that should work +DELETE FROM PKTABLE where ptest1=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE where ptest1=2; + ^ +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: SELECT * from PKTABLE ORDER BY 1, 2, 3,4; + ^ +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; +ERROR: ORDER BY position 3 is not in select list +LINE 1: SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ^ +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +ERROR: table "PKTABLE" does not exist +-- cascade update/delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE + ON DELETE CASCADE ON UPDATE CASCADE); +ERROR: relation "PKTABLE" does not exist +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); + ^ +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); + ^ +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); + ^ +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); + ^ +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, 2, 3, 1); + ^ +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); + ^ +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); + ^ +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); + ^ +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); + ^ +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, 2, 7, 6); + ^ +-- Show FKTABLE +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ^ +-- Try to update something that will cascade +UPDATE PKTABLE set ptest2=5 where ptest2=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE set ptest2=5 where ptest2=2; + ^ +-- Try to update something that should not cascade +UPDATE PKTABLE set ptest1=1 WHERE ptest2=3; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE set ptest1=1 WHERE ptest2=3; + ^ +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: SELECT * from PKTABLE ORDER BY 1, 2, 3,4; + ^ +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ^ +-- Try to delete something that should cascade +DELETE FROM PKTABLE where ptest1=1 and ptest2=5 and ptest3=3; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE where ptest1=1 and ptest2=5 and ptest3=3... + ^ +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: SELECT * from PKTABLE ORDER BY 1, 2, 3,4; + ^ +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ^ +-- Try to delete something that should not have a cascade +DELETE FROM PKTABLE where ptest1=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE where ptest1=2; + ^ +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: SELECT * from PKTABLE ORDER BY 1, 2, 3,4; + ^ +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ^ +DROP TABLE FKTABLE; +ERROR: table "FKTABLE" does not exist +DROP TABLE PKTABLE; +ERROR: table "PKTABLE" does not exist +-- set null update / set default delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( ftest1 int DEFAULT 0, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE + ON DELETE SET DEFAULT ON UPDATE SET NULL); +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +INSERT INTO FKTABLE VALUES (2, 3, 4, 1); +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname3" +DETAIL: Key (ftest1, ftest2, ftest3)=(1, 2, 7) is not present in table "PKTABLE". +-- Show FKTABLE +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 1 | 2 | 3 | 1 + 2 | 3 | 4 | 1 + 2 | | 3 | 3 + | 2 | 3 | 2 + | 2 | 7 | 4 + | 3 | 4 | 5 +(6 rows) + +-- Try to update something that will set null +UPDATE PKTABLE set ptest2=5 where ptest2=2; +-- Try to update something that should not set null +UPDATE PKTABLE set ptest2=2 WHERE ptest2=3 and ptest1=1; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE ORDER BY 1, 2, 3,4; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 1 | 2 | 3 | test2 + 1 | 5 | 3 | test1 + 2 | 3 | 4 | test3 + 2 | 4 | 5 | test4 +(4 rows) + +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 1 | | 3 | 1 + 2 | 3 | 4 | 1 + 2 | | 3 | 3 + | 2 | 3 | 2 + | 2 | 7 | 4 + | 3 | 4 | 5 +(6 rows) + +-- Try to delete something that should set default +DELETE FROM PKTABLE where ptest1=2 and ptest2=3 and ptest3=4; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE ORDER BY 1, 2, 3,4; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 1 | 2 | 3 | test2 + 1 | 5 | 3 | test1 + 2 | 4 | 5 | test4 +(3 rows) + +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 0 | | | 1 + 1 | | 3 | 1 + 2 | | 3 | 3 + | 2 | 3 | 2 + | 2 | 7 | 4 + | 3 | 4 | 5 +(6 rows) + +-- Try to delete something that should not set default +DELETE FROM PKTABLE where ptest2=5; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE ORDER BY 1, 2, 3,4; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 1 | 2 | 3 | test2 + 2 | 4 | 5 | test4 +(2 rows) + +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 0 | | | 1 + 1 | | 3 | 1 + 2 | | 3 | 3 + | 2 | 3 | 2 + | 2 | 7 | 4 + | 3 | 4 | 5 +(6 rows) + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +-- set default update / set null delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE FKTABLE ( ftest1 int DEFAULT 0, ftest2 int DEFAULT -1, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE + ON DELETE SET NULL ON UPDATE SET DEFAULT) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); + ^ +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); + ^ +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); + ^ +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); + ^ +INSERT INTO PKTABLE VALUES (2, -1, 5, 'test5'); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES (2, -1, 5, 'test5'); + ^ +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, 2, 3, 1); + ^ +INSERT INTO FKTABLE VALUES (2, 3, 4, 1); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (2, 3, 4, 1); + ^ +INSERT INTO FKTABLE VALUES (2, 4, 5, 1); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (2, 4, 5, 1); + ^ +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); + ^ +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); + ^ +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); + ^ +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); + ^ +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES (1, 2, 7, 6); + ^ +-- Show FKTABLE +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ^ +-- Try to update something that will fail +UPDATE PKTABLE set ptest2=5 where ptest2=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE set ptest2=5 where ptest2=2; + ^ +-- Try to update something that will set default +UPDATE PKTABLE set ptest1=0, ptest2=5, ptest3=10 where ptest2=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE set ptest1=0, ptest2=5, ptest3=10 where ptest... + ^ +UPDATE PKTABLE set ptest2=10 where ptest2=4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE set ptest2=10 where ptest2=4; + ^ +-- Try to update something that should not set default +UPDATE PKTABLE set ptest2=2 WHERE ptest2=3 and ptest1=1; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: UPDATE PKTABLE set ptest2=2 WHERE ptest2=3 and ptest1=1; + ^ +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: SELECT * from PKTABLE ORDER BY 1, 2, 3,4; + ^ +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ^ +-- Try to delete something that should set null +DELETE FROM PKTABLE where ptest1=2 and ptest2=3 and ptest3=4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE where ptest1=2 and ptest2=3 and ptest3=4... + ^ +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: SELECT * from PKTABLE ORDER BY 1, 2, 3,4; + ^ +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ^ +-- Try to delete something that should not set null +DELETE FROM PKTABLE where ptest2=5; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: DELETE FROM PKTABLE where ptest2=5; + ^ +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: SELECT * from PKTABLE ORDER BY 1, 2, 3,4; + ^ +SELECT * from FKTABLE ORDER BY 1, 2, 3,4; +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: SELECT * from FKTABLE ORDER BY 1, 2, 3,4; + ^ +DROP TABLE FKTABLE; +ERROR: table "FKTABLE" does not exist +DROP TABLE PKTABLE; +ERROR: table "PKTABLE" does not exist +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE_FAIL1 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest2) REFERENCES PKTABLE); +ERROR: column "ftest2" referenced in foreign key constraint does not exist +CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1) REFERENCES PKTABLE(ptest2)); +ERROR: column "ptest2" referenced in foreign key constraint does not exist +DROP TABLE FKTABLE_FAIL1; +ERROR: table "FKTABLE_FAIL1" does not exist +DROP TABLE FKTABLE_FAIL2; +ERROR: table "FKTABLE_FAIL2" does not exist +DROP TABLE PKTABLE; +-- Test for referencing column number smaller than referenced constraint +CREATE TABLE PKTABLE (ptest1 int, ptest2 int, UNIQUE(ptest1, ptest2)); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "PKTABLE_ptest1_ptest2_key" for table "PKTABLE" +CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES pktable(ptest1)); +ERROR: relation "pktable" does not exist +DROP TABLE FKTABLE_FAIL1; +ERROR: table "FKTABLE_FAIL1" does not exist +DROP TABLE PKTABLE; +-- +-- Tests for mismatched types +-- +-- Basic one column, two table setup +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +INSERT INTO PKTABLE VALUES(42); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES(42); + ^ +-- This next should fail, because int=inet does not exist +CREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable); +ERROR: relation "pktable" does not exist +-- This should also fail for the same reason, but here we +-- give the column name +CREATE TABLE FKTABLE (ftest1 inet REFERENCES pktable(ptest1)) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- This should succeed, even though they are different types, +-- because int=int8 exists and is a member of the integer opfamily +CREATE TABLE FKTABLE (ftest1 int8 REFERENCES pktable) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- Check it actually works +INSERT INTO FKTABLE VALUES(42); -- should succeed +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES(42); + ^ +INSERT INTO FKTABLE VALUES(43); -- should fail +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES(43); + ^ +UPDATE FKTABLE SET ftest1 = ftest1; -- should succeed +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: UPDATE FKTABLE SET ftest1 = ftest1; + ^ +UPDATE FKTABLE SET ftest1 = ftest1 + 1; -- should fail +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: UPDATE FKTABLE SET ftest1 = ftest1 + 1; + ^ +DROP TABLE FKTABLE; +ERROR: table "FKTABLE" does not exist +-- This should fail, because we'd have to cast numeric to int which is +-- not an implicit coercion (or use numeric=numeric, but that's not part +-- of the integer opfamily) +CREATE TABLE FKTABLE (ftest1 numeric REFERENCES pktable) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +DROP TABLE PKTABLE; +ERROR: table "PKTABLE" does not exist +-- On the other hand, this should work because int implicitly promotes to +-- numeric, and we allow promotion on the FK side +CREATE TABLE PKTABLE (ptest1 numeric PRIMARY KEY) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +INSERT INTO PKTABLE VALUES(42); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO PKTABLE VALUES(42); + ^ +CREATE TABLE FKTABLE (ftest1 int REFERENCES pktable) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- Check it actually works +INSERT INTO FKTABLE VALUES(42); -- should succeed +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES(42); + ^ +INSERT INTO FKTABLE VALUES(43); -- should fail +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: INSERT INTO FKTABLE VALUES(43); + ^ +UPDATE FKTABLE SET ftest1 = ftest1; -- should succeed +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: UPDATE FKTABLE SET ftest1 = ftest1; + ^ +UPDATE FKTABLE SET ftest1 = ftest1 + 1; -- should fail +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: UPDATE FKTABLE SET ftest1 = ftest1 + 1; + ^ +DROP TABLE FKTABLE; +ERROR: table "FKTABLE" does not exist +DROP TABLE PKTABLE; +ERROR: table "PKTABLE" does not exist +-- Two columns, two tables +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2)) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- This should fail, because we just chose really odd types +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- Again, so should this... +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2)) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- This fails because we mixed up the column ordering +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- As does this... +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest1, ptest2)) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- And again.. +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest2, ptest1)) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- This works... +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES pktable(ptest2, ptest1)) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +DROP TABLE FKTABLE; +ERROR: table "FKTABLE" does not exist +-- As does this +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES pktable(ptest1, ptest2)) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +DROP TABLE FKTABLE; +ERROR: table "FKTABLE" does not exist +DROP TABLE PKTABLE; +ERROR: table "PKTABLE" does not exist +-- Two columns, same table +-- Make sure this still works... +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES pktable(ptest1, ptest2)); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +ERROR: relation "pktable" does not exist +DROP TABLE PKTABLE; +ERROR: table "PKTABLE" does not exist +-- And this, +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES pktable); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +ERROR: relation "pktable" does not exist +DROP TABLE PKTABLE; +ERROR: table "PKTABLE" does not exist +-- This shouldn't (mixed up columns) +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES pktable(ptest2, ptest1)); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +ERROR: relation "pktable" does not exist +-- Nor should this... (same reason, we have 4,3 referencing 1,2 which mismatches types +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, +ptest3) REFERENCES pktable(ptest1, ptest2)); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +ERROR: relation "pktable" does not exist +-- Not this one either... Same as the last one except we didn't defined the columns being referenced. +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, +ptest3) REFERENCES pktable); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +ERROR: relation "pktable" does not exist +-- +-- Now some cases with inheritance +-- Basic 2 table case: 1 column of matching types. +create table pktable_base (base1 int not null) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +create table pktable (ptest1 int, primary key(base1), unique(base1, ptest1)) inherits (pktable_base) DISTRIBUTE BY REPLICATION; +ERROR: CREATE TABLE ... INHERITS is not yet supported. +create table fktable (ftest1 int references pktable(base1)); +ERROR: relation "pktable" does not exist +-- now some ins, upd, del +insert into pktable(base1) values (1); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable(base1) values (1); + ^ +insert into pktable(base1) values (2); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable(base1) values (2); + ^ +-- let's insert a non-existent fktable value +insert into fktable(ftest1) values (3); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: insert into fktable(ftest1) values (3); + ^ +-- let's make a valid row for that +insert into pktable(base1) values (3); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable(base1) values (3); + ^ +insert into fktable(ftest1) values (3); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: insert into fktable(ftest1) values (3); + ^ +-- let's try removing a row that should fail from pktable +delete from pktable where base1>2; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: delete from pktable where base1>2; + ^ +-- okay, let's try updating all of the base1 values to *4 +-- which should fail. +update pktable set base1=base1*4; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: update pktable set base1=base1*4; + ^ +-- okay, let's try an update that should work. +update pktable set base1=base1*4 where base1<3; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: update pktable set base1=base1*4 where base1<3; + ^ +-- and a delete that should work +delete from pktable where base1>3; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: delete from pktable where base1>3; + ^ +-- cleanup +drop table fktable; +ERROR: table "fktable" does not exist +delete from pktable; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: delete from pktable; + ^ +-- Now 2 columns 2 tables, matching types +create table fktable (ftest1 int, ftest2 int, foreign key(ftest1, ftest2) references pktable(base1, ptest1)); +ERROR: relation "pktable" does not exist +-- now some ins, upd, del +insert into pktable(base1, ptest1) values (1, 1); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable(base1, ptest1) values (1, 1); + ^ +insert into pktable(base1, ptest1) values (2, 2); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable(base1, ptest1) values (2, 2); + ^ +-- let's insert a non-existent fktable value +insert into fktable(ftest1, ftest2) values (3, 1); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: insert into fktable(ftest1, ftest2) values (3, 1); + ^ +-- let's make a valid row for that +insert into pktable(base1,ptest1) values (3, 1); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable(base1,ptest1) values (3, 1); + ^ +insert into fktable(ftest1, ftest2) values (3, 1); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: insert into fktable(ftest1, ftest2) values (3, 1); + ^ +-- let's try removing a row that should fail from pktable +delete from pktable where base1>2; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: delete from pktable where base1>2; + ^ +-- okay, let's try updating all of the base1 values to *4 +-- which should fail. +update pktable set base1=base1*4; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: update pktable set base1=base1*4; + ^ +-- okay, let's try an update that should work. +update pktable set base1=base1*4 where base1<3; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: update pktable set base1=base1*4 where base1<3; + ^ +-- and a delete that should work +delete from pktable where base1>3; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: delete from pktable where base1>3; + ^ +-- cleanup +drop table fktable; +ERROR: table "fktable" does not exist +drop table pktable; +ERROR: table "pktable" does not exist +drop table pktable_base; +ERROR: table "pktable_base" does not exist +-- Now we'll do one all in 1 table with 2 columns of matching types +create table pktable_base(base1 int not null, base2 int) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +create table pktable(ptest1 int, ptest2 int, primary key(base1, ptest1), foreign key(base2, ptest2) references + pktable(base1, ptest1)) inherits (pktable_base) DISTRIBUTE BY REPLICATION; +ERROR: CREATE TABLE ... INHERITS is not yet supported. +insert into pktable (base1, ptest1, base2, ptest2) values (1, 1, 1, 1); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable (base1, ptest1, base2, ptest2) values (1... + ^ +insert into pktable (base1, ptest1, base2, ptest2) values (2, 1, 1, 1); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable (base1, ptest1, base2, ptest2) values (2... + ^ +insert into pktable (base1, ptest1, base2, ptest2) values (2, 2, 2, 1); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable (base1, ptest1, base2, ptest2) values (2... + ^ +insert into pktable (base1, ptest1, base2, ptest2) values (1, 3, 2, 2); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable (base1, ptest1, base2, ptest2) values (1... + ^ +-- fails (3,2) isn't in base1, ptest1 +insert into pktable (base1, ptest1, base2, ptest2) values (2, 3, 3, 2); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: insert into pktable (base1, ptest1, base2, ptest2) values (2... + ^ +-- fails (2,2) is being referenced +delete from pktable where base1=2; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: delete from pktable where base1=2; + ^ +-- fails (1,1) is being referenced (twice) +update pktable set base1=3 where base1=1; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: update pktable set base1=3 where base1=1; + ^ +-- this sequence of two deletes will work, since after the first there will be no (2,*) references +delete from pktable where base2=2; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: delete from pktable where base2=2; + ^ +delete from pktable where base1=2; +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: delete from pktable where base1=2; + ^ +drop table pktable; +ERROR: table "pktable" does not exist +drop table pktable_base; +ERROR: table "pktable_base" does not exist +-- 2 columns (2 tables), mismatched types +create table pktable_base(base1 int not null) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +create table pktable(ptest1 inet, primary key(base1, ptest1)) inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +-- just generally bad types (with and without column references on the referenced table) +create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable); +ERROR: relation "pktable" does not exist +create table fktable(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references pktable(base1, ptest1)) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- let's mix up which columns reference which +create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +create table fktable(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references pktable(base1, ptest1)) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +create table fktable(ftest1 int, ftest2 inet, foreign key(ftest1, ftest2) references pktable(ptest1, base1))distribute by hash(ftest1); +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +drop table pktable; +ERROR: table "pktable" does not exist +drop table pktable_base; +ERROR: table "pktable_base" does not exist +-- 2 columns (1 table), mismatched types +create table pktable_base(base1 int not null, base2 int); +create table pktable(ptest1 inet, ptest2 inet[], primary key(base1, ptest1), foreign key(base2, ptest2) references + pktable(base1, ptest1)) inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(base2, ptest2) references + pktable(ptest1, base1)) inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references + pktable(base1, ptest1)) inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +create table pktable(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references + pktable(base1, ptest1)) inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +drop table pktable; +ERROR: table "pktable" does not exist +drop table pktable_base; +-- +-- Deferrable constraints +-- (right now, only FOREIGN KEY constraints can be deferred) +-- +-- deferrable, explicitly deferred +CREATE TABLE pktable ( + id INT4 PRIMARY KEY, + other INT4 +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE fktable ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES pktable DEFERRABLE +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- default to immediate: should fail +INSERT INTO fktable VALUES (5, 10); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: INSERT INTO fktable VALUES (5, 10); + ^ +-- explicitly defer the constraint +START TRANSACTION; +SET CONSTRAINTS ALL DEFERRED; +INSERT INTO fktable VALUES (10, 15); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: INSERT INTO fktable VALUES (10, 15); + ^ +INSERT INTO pktable VALUES (15, 0); -- make the FK insert valid +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +COMMIT; +DROP TABLE fktable, pktable; +ERROR: table "fktable" does not exist +-- deferrable, initially deferred +CREATE TABLE pktable ( + id INT4 PRIMARY KEY, + other INT4 +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE fktable ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES pktable DEFERRABLE INITIALLY DEFERRED +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- default to deferred, should succeed +START TRANSACTION; +INSERT INTO fktable VALUES (100, 200); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: INSERT INTO fktable VALUES (100, 200); + ^ +INSERT INTO pktable VALUES (200, 500); -- make the FK insert valid +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +COMMIT; +-- default to deferred, explicitly make immediate +START TRANSACTION; +SET CONSTRAINTS ALL IMMEDIATE; +-- should fail +INSERT INTO fktable VALUES (500, 1000); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: INSERT INTO fktable VALUES (500, 1000); + ^ +COMMIT; +DROP TABLE fktable, pktable; +ERROR: table "fktable" does not exist +-- tricky behavior: according to SQL99, if a deferred constraint is set +-- to 'immediate' mode, it should be checked for validity *immediately*, +-- not when the current transaction commits (i.e. the mode change applies +-- retroactively) +CREATE TABLE pktable ( + id INT4 PRIMARY KEY, + other INT4 +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE fktable ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES pktable DEFERRABLE +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +START TRANSACTION; +SET CONSTRAINTS ALL DEFERRED; +-- should succeed, for now +INSERT INTO fktable VALUES (1000, 2000); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: INSERT INTO fktable VALUES (1000, 2000); + ^ +-- should cause transaction abort, due to preceding error +SET CONSTRAINTS ALL IMMEDIATE; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +INSERT INTO pktable VALUES (2000, 3); -- too late +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +COMMIT; +DROP TABLE fktable, pktable; +ERROR: table "fktable" does not exist +-- deferrable, initially deferred +CREATE TABLE pktable ( + id INT4 PRIMARY KEY, + other INT4 +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TABLE fktable ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES pktable DEFERRABLE INITIALLY DEFERRED +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +START TRANSACTION; +-- no error here +INSERT INTO fktable VALUES (100, 200); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: INSERT INTO fktable VALUES (100, 200); + ^ +-- error here on commit +COMMIT; +DROP TABLE pktable, fktable; +ERROR: table "pktable" does not exist +-- test notice about expensive referential integrity checks, +-- where the index cannot be used because of type incompatibilities. +-- Enforce use of COMMIT instead of 2PC for temporary objects +CREATE TEMP TABLE pktable ( + id1 INT4 PRIMARY KEY, + id2 VARCHAR(4) UNIQUE, + id3 REAL UNIQUE, + UNIQUE(id1, id2, id3) +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TEMP TABLE fktable ( + x1 INT4 REFERENCES pktable(id1), + x2 VARCHAR(4) REFERENCES pktable(id2), + x3 REAL REFERENCES pktable(id3), + x4 TEXT, + x5 INT2 +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +-- check individual constraints with alter table. +-- should fail +-- varchar does not promote to real +ALTER TABLE fktable ADD CONSTRAINT fk_2_3 +FOREIGN KEY (x2) REFERENCES pktable(id3); +ERROR: relation "fktable" does not exist +-- nor to int4 +ALTER TABLE fktable ADD CONSTRAINT fk_2_1 +FOREIGN KEY (x2) REFERENCES pktable(id1); +ERROR: relation "fktable" does not exist +-- real does not promote to int4 +ALTER TABLE fktable ADD CONSTRAINT fk_3_1 +FOREIGN KEY (x3) REFERENCES pktable(id1); +ERROR: relation "fktable" does not exist +-- int4 does not promote to text +ALTER TABLE fktable ADD CONSTRAINT fk_1_2 +FOREIGN KEY (x1) REFERENCES pktable(id2); +ERROR: relation "fktable" does not exist +-- should succeed +-- int4 promotes to real +ALTER TABLE fktable ADD CONSTRAINT fk_1_3 +FOREIGN KEY (x1) REFERENCES pktable(id3); +ERROR: relation "fktable" does not exist +-- text is compatible with varchar +ALTER TABLE fktable ADD CONSTRAINT fk_4_2 +FOREIGN KEY (x4) REFERENCES pktable(id2); +ERROR: relation "fktable" does not exist +-- int2 is part of integer opfamily as of 8.0 +ALTER TABLE fktable ADD CONSTRAINT fk_5_1 +FOREIGN KEY (x5) REFERENCES pktable(id1); +ERROR: relation "fktable" does not exist +-- check multikey cases, especially out-of-order column lists +-- these should work +ALTER TABLE fktable ADD CONSTRAINT fk_123_123 +FOREIGN KEY (x1,x2,x3) REFERENCES pktable(id1,id2,id3); +ERROR: relation "fktable" does not exist +ALTER TABLE fktable ADD CONSTRAINT fk_213_213 +FOREIGN KEY (x2,x1,x3) REFERENCES pktable(id2,id1,id3); +ERROR: relation "fktable" does not exist +ALTER TABLE fktable ADD CONSTRAINT fk_253_213 +FOREIGN KEY (x2,x5,x3) REFERENCES pktable(id2,id1,id3); +ERROR: relation "fktable" does not exist +-- these should fail +ALTER TABLE fktable ADD CONSTRAINT fk_123_231 +FOREIGN KEY (x1,x2,x3) REFERENCES pktable(id2,id3,id1); +ERROR: relation "fktable" does not exist +ALTER TABLE fktable ADD CONSTRAINT fk_241_132 +FOREIGN KEY (x2,x4,x1) REFERENCES pktable(id1,id3,id2); +ERROR: relation "fktable" does not exist +DROP TABLE pktable, fktable; +ERROR: table "pktable" does not exist +-- test a tricky case: we can elide firing the FK check trigger during +-- an UPDATE if the UPDATE did not change the foreign key +-- field. However, we can't do this if our transaction was the one that +-- created the updated row and the trigger is deferred, since our UPDATE +-- will have invalidated the original newly-inserted tuple, and therefore +-- cause the on-INSERT RI trigger not to be fired. +CREATE TEMP TABLE pktable ( + id int primary key, + other int +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +CREATE TEMP TABLE fktable ( + id int primary key, + fk int references pktable deferrable initially deferred +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +INSERT INTO pktable VALUES (5, 10); +ERROR: relation "pktable" does not exist on datanode1 +LINE 1: INSERT INTO pktable VALUES (5, 10); + ^ +START TRANSACTION; +-- doesn't match PK, but no error yet +INSERT INTO fktable VALUES (0, 20); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: INSERT INTO fktable VALUES (0, 20); + ^ +-- don't change FK +UPDATE fktable SET id = id + 1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +-- should catch error from initial INSERT +COMMIT; +-- check same case when insert is in a different subtransaction than update +START TRANSACTION; +-- doesn't match PK, but no error yet +INSERT INTO fktable VALUES (0, 20); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: INSERT INTO fktable VALUES (0, 20); + ^ +-- UPDATE will be in a subxact +SAVEPOINT savept1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +-- don't change FK +UPDATE fktable SET id = id + 1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +-- should catch error from initial INSERT +COMMIT; +START TRANSACTION; +-- INSERT will be in a subxact +SAVEPOINT savept1; +-- doesn't match PK, but no error yet +INSERT INTO fktable VALUES (0, 20); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: INSERT INTO fktable VALUES (0, 20); + ^ +RELEASE SAVEPOINT savept1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +-- don't change FK +UPDATE fktable SET id = id + 1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +-- should catch error from initial INSERT +COMMIT; +START TRANSACTION; +-- doesn't match PK, but no error yet +INSERT INTO fktable VALUES (0, 20); +ERROR: relation "fktable" does not exist on datanode1 +LINE 1: INSERT INTO fktable VALUES (0, 20); + ^ +-- UPDATE will be in a subxact +SAVEPOINT savept1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +-- don't change FK +UPDATE fktable SET id = id + 1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +-- Roll back the UPDATE +ROLLBACK TO savept1; +ERROR: no such savepoint +-- should catch error from initial INSERT +COMMIT; +-- test order of firing of FK triggers when several RI-induced changes need to +-- be made to the same row. This was broken by subtransaction-related +-- changes in 8.0. +CREATE TEMP TABLE users ( + id INT PRIMARY KEY, + name VARCHAR NOT NULL +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +INSERT INTO users VALUES (1, 'Jozko'); +ERROR: relation "users" does not exist on datanode1 +LINE 1: INSERT INTO users VALUES (1, 'Jozko'); + ^ +INSERT INTO users VALUES (2, 'Ferko'); +ERROR: relation "users" does not exist on datanode1 +LINE 1: INSERT INTO users VALUES (2, 'Ferko'); + ^ +INSERT INTO users VALUES (3, 'Samko'); +ERROR: relation "users" does not exist on datanode1 +LINE 1: INSERT INTO users VALUES (3, 'Samko'); + ^ +CREATE TEMP TABLE tasks ( + id INT PRIMARY KEY, + owner INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL, + worker INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL, + checked_by INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +INSERT INTO tasks VALUES (1,1,NULL,NULL); +ERROR: relation "tasks" does not exist on datanode1 +LINE 1: INSERT INTO tasks VALUES (1,1,NULL,NULL); + ^ +INSERT INTO tasks VALUES (2,2,2,NULL); +ERROR: relation "tasks" does not exist on datanode1 +LINE 1: INSERT INTO tasks VALUES (2,2,2,NULL); + ^ +INSERT INTO tasks VALUES (3,3,3,3); +ERROR: relation "tasks" does not exist on datanode1 +LINE 1: INSERT INTO tasks VALUES (3,3,3,3); + ^ +SELECT * FROM tasks ORDER BY 1, 2, 3,4; +ERROR: relation "tasks" does not exist on datanode1 +LINE 1: SELECT * FROM tasks ORDER BY 1, 2, 3,4; + ^ +UPDATE users SET id = 4 WHERE id = 3; +ERROR: relation "users" does not exist on datanode1 +LINE 1: UPDATE users SET id = 4 WHERE id = 3; + ^ +SELECT * FROM tasks ORDER BY 1, 2, 3,4; +ERROR: relation "tasks" does not exist on datanode1 +LINE 1: SELECT * FROM tasks ORDER BY 1, 2, 3,4; + ^ +DELETE FROM users WHERE id = 4; +ERROR: relation "users" does not exist on datanode1 +LINE 1: DELETE FROM users WHERE id = 4; + ^ +SELECT * FROM tasks ORDER BY 1, 2, 3,4; +ERROR: relation "tasks" does not exist on datanode1 +LINE 1: SELECT * FROM tasks ORDER BY 1, 2, 3,4; + ^ +-- could fail with only 2 changes to make, if row was already updated +START TRANSACTION; +UPDATE tasks set id=id WHERE id=2; +ERROR: relation "tasks" does not exist on datanode1 +LINE 1: UPDATE tasks set id=id WHERE id=2; + ^ +SELECT * FROM tasks ORDER BY 1, 2, 3,4; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +DELETE FROM users WHERE id = 2; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +SELECT * FROM tasks ORDER BY 1, 2, 3,4; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +COMMIT; +-- +-- Test self-referential FK with CASCADE (bug #6268) +-- +create temp table selfref ( + a int primary key, + b int, + foreign key (b) references selfref (a) + on update cascade on delete cascade +) DISTRIBUTE BY REPLICATION; +ERROR: Un-support feature +DETAIL: The distributed capability is not supported currently. +insert into selfref (a, b) +values + (0, 0), + (1, 1); +ERROR: relation "selfref" does not exist on datanode1 +LINE 1: insert into selfref (a, b) + ^ +start transaction; + update selfref set a = 123 where a = 0; +ERROR: relation "selfref" does not exist on datanode1 +LINE 1: update selfref set a = 123 where a = 0; + ^ + select a, b from selfref; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] + update selfref set a = 456 where a = 123; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] + select a, b from selfref; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +commit; diff --git a/contrib/dolphin/expected/case_sensitive_test/insert.out b/contrib/dolphin/expected/case_sensitive_test/insert.out new file mode 100644 index 0000000000000000000000000000000000000000..f9d56f9c7b642adb353db4281442e15bcefa3c5e --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/insert.out @@ -0,0 +1,2 @@ +\c table_name_test_db;te_test +\connect: FATAL: database "table_name_test_db;te_test" does not exist diff --git a/contrib/dolphin/expected/case_sensitive_test/reindex_internal.out b/contrib/dolphin/expected/case_sensitive_test/reindex_internal.out new file mode 100644 index 0000000000000000000000000000000000000000..5cef14afd44f0e2c508eb9b8c2d6b09505e922af --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/reindex_internal.out @@ -0,0 +1,248 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +--REINDEX INTERNAL TABLE name [PARTITION name]: +-- used to reindex the index of the cudesc table. +drop schema if exists reindexinternal cascade; +NOTICE: schema "reindexinternal" does not exist, skipping +create schema reindexinternal; +set current_schema = reindexinternal; +set max_query_retry_times = 3; +--case1 reindex internal table col_tb; +drop table if exists T1; +NOTICE: table "T1" does not exist, skipping +create table T1(a int, b int)with (orientation=column); +insert into T1 values (1,1); +insert into T1 values (1,2); +insert into T1 values (2,1); +create index a_idx_t1 on T1 using btree(a); +reindex index a_idx_t1; +reindex table T1; +reindex internal table T1; +--case2 reindex internal table col_part_tb; +drop table if exists T2; +NOTICE: table "T2" does not exist, skipping +create table T2( + c_id varchar, + c_w_id integer, + c_date date, + partial cluster key(c_id,c_w_id) + ) with (orientation=column,max_batchrow= 30700, compression = middle) +partition by range (c_date,c_w_id) +( + PARTITION t2_1 values less than ('20170331',5), + PARTITION t2_2 values less than ('20170731',450), + PARTITION t2_3 values less than ('20170930',1062), + PARTITION t2_4 values less than ('20171231',1765), + PARTITION t2_5 values less than ('20180331',2024), + PARTITION t2_6 values less than ('20180731',2384), + PARTITION t2_7 values less than ('20180930',2786), + PARTITION t2_8 values less than (maxvalue,maxvalue) +); +insert into T2 values('gauss1',4,'20170301'); +insert into T2 values('gauss2',400,'20170625'); +insert into T2 values('gauss3',480,'20170920'); +insert into T2 values('gauss4',1065,'20170920'); +insert into T2 values('gauss5',1800,'20170920'); +insert into T2 values('gauss6',2030,'20170920'); +insert into T2 values('gauss7',2385,'20170920'); +insert into T2 values('gauss8',2789,'20191020'); +insert into T2 values('gauss9',2789,'20171020'); +create index idx_t2 on T2 using btree(c_id) LOCAL; +create index idx2_t2 on T2 using btree(c_id) LOCAL ( + PARTITION t2_1_index, + PARTITION t2_2_index, + PARTITION t2_3_index, + PARTITION t2_4_index, + PARTITION t2_5_index, + PARTITION t2_6_index, + PARTITION t2_7_index, + PARTITION t2_8_index +); +reindex index idx_t2; +reindex index idx2_t2 partition t2_1_index; +reindex table T2; +reindex internal table T2; +reindex table T2 partition t2_1; +reindex internal table T2 partition t2_1; +--case3 reindex internal table col_part_tb partition part_name; +drop table if exists T3; +NOTICE: table "T3" does not exist, skipping +CREATE TABLE T3( +CA_ADDRESS_SK INTEGER NOT NULL, +CA_ADDRESS_ID CHAR(16) NOT NULL, +CA_STREET_NUMBER CHAR(10) , +CA_STREET_NAME VARCHAR(60) , +CA_STREET_TYPE CHAR(15) , +CA_SUITE_NUMBER CHAR(10) , +CA_CITY VARCHAR(60) , +CA_COUNTY VARCHAR(30) , +CA_STATE CHAR(2) , +CA_ZIP CHAR(10) , +CA_COUNTRY VARCHAR(20) , +CA_GMT_OFFSET DECIMAL(5,2) , +CA_LOCATION_TYPE CHAR(20) +)with (orientation=column,max_batchrow= 30700, compression = middle) +PARTITION BY RANGE(CA_ADDRESS_SK) +( PARTITION t3_1 VALUES LESS THAN (3000), + PARTITION t3_2 VALUES LESS THAN (5000), + PARTITION t3_3 VALUES LESS THAN (MAXVALUE) +)ENABLE ROW MOVEMENT; +CREATE INDEX t3_idx ON T3(CA_ADDRESS_SK) LOCAL; +CREATE INDEX t3_idx2 ON T3(CA_ADDRESS_SK) LOCAL( + PARTITION CA_ADDRESS_SK_index1, + PARTITION CA_ADDRESS_SK_index2, + PARTITION CA_ADDRESS_SK_index3 +); + +reindex index t3_idx2 partition CA_ADDRESS_SK_index1; +reindex table T3 partition t3_1; +reindex internal table T3 partition t3_2; +--case4 reindex internal table col_rep_tb partition part_name; +drop table if exists T4; +NOTICE: table "T4" does not exist, skipping +create table T4( + c_id varchar, + c_w_id integer, + c_date date, + partial cluster key(c_id,c_w_id) + ) with (orientation=column,max_batchrow= 30700, compression = middle) +partition by range (c_date,c_w_id) +( + PARTITION t4_1 values less than ('20170331',5), + PARTITION t4_2 values less than ('20170731',450), + PARTITION t4_3 values less than ('20170930',1062), + PARTITION t4_4 values less than ('20171231',1765), + PARTITION t4_5 values less than ('20180331',2024), + PARTITION t4_6 values less than ('20180731',2384), + PARTITION t4_7 values less than ('20180930',2786), + PARTITION t4_8 values less than (maxvalue,maxvalue) +); +insert into T4 values('gauss1',4,'20170301'); +insert into T4 values('gauss2',400,'20170625'); +insert into T4 values('gauss3',480,'20170920'); +insert into T4 values('gauss4',1065,'20170920'); +insert into T4 values('gauss5',1800,'20170920'); +insert into T4 values('gauss6',2030,'20170920'); +insert into T4 values('gauss7',2385,'20170920'); +insert into T4 values('gauss8',2789,'20191020'); +insert into T4 values('gauss9',2789,'20171020'); +create index a_idx_t4 on T4 using btree(c_id) LOCAL; +reindex index a_idx_t4; +reindex table T4; +reindex internal table T4; +reindex table T4 partition t4_1; +reindex internal table T4 partition t4_1; +--case5 reindex internal table temp_tb; +drop table if exists T5; +NOTICE: table "T5" does not exist, skipping +create temp table T5(a int, b int)with (orientation=column); +insert into T5 values (1,1); +insert into T5 values (1,2); +insert into T5 values (2,1); +create index a_idx_t5 on T5 using btree(a); +reindex index a_idx_t5; +reindex table T5; +reindex internal table T5; +--case6 reindex internal table unlog_tb; +drop table if exists T6; +NOTICE: table "T6" does not exist, skipping +create unlogged table T6 +( +c_int int, +c_tinyint tinyint, +c_smallint smallint, +c_integer integer, +c_bigint bigint, +c_numeric numeric, +c_decimal decimal, +c_real real, +c_float4 float4, +c_float8 float8, +c_double1 double precision, +c_double2 binary_double, +c_char1 char(100), +c_char2 character(100), +c_char3 nchar(100), +c_char4 varchar(100), +c_char5 character varying(100), +c_char6 nvarchar2(100), +c_char7 varchar2(100), +c_clob text, +c_text text, +c_date date, +c_time1 time with time zone, +c_time2 time without time zone, +c_timestamp1 timestamp with time zone, +c_timestamp2 timestamp without time zone, +c_smalldatetime smalldatetime, +c_interval interval, +c_boolean boolean, +c_oid oid, +c_money money +)with(orientation=column); +create index a_idx_t6 on T6 using btree(a); +ERROR: column "a" does not exist +reindex index a_idx_t6; +ERROR: relation "a_idx_t6" does not exist +reindex table T6; +NOTICE: table "T6" has no indexes +reindex internal table T6; +--case7 reindex internal table row_tb; +drop table if exists T7; +NOTICE: table "T7" does not exist, skipping +create table T7(a int, b int); +insert into T7 values (1,1); +insert into T7 values (1,2); +insert into T7 values (2,1); +create index a_idx_t7 on T7 (a); +reindex index a_idx_t7; +reindex table T7; +reindex internal table T7; +ERROR: The table "T7" doesn't support the operation of 'REINDEX INTERNAL TABLE'. There is no Desc table on it. +--case8 reindex单个并发执行+并发分区表+并发分区表的分区+混合并发; +\parallel on +reindex internal table T1; +reindex internal table T1; +reindex internal table T1; +reindex internal table T1; +reindex internal table T1; +\parallel off +\parallel on +reindex internal table T2; +reindex internal table T2; +reindex internal table T2; +reindex internal table T2; +reindex internal table T2; +\parallel off +\parallel on +reindex internal table T2 partition t2_2; +reindex internal table T2 partition t2_3; +reindex internal table T2 partition t2_1; +reindex internal table T2 partition t2_8; +reindex internal table T2 partition t2_5; +reindex internal table T2 partition t2_4; +reindex internal table T2 partition t2_6; +reindex internal table T2 partition t2_7; +\parallel off +\parallel on +reindex internal table T3 partition t3_2; +reindex internal table T3 partition t3_2; +reindex internal table T3 partition t3_2; +reindex internal table T3 partition t3_2; +reindex internal table T3 partition t3_2; +\parallel off +\parallel on +reindex internal table T1; +reindex internal table T3 partition t3_3; +reindex internal table T2; +reindex internal table T3; +reindex internal table T3 partition t3_1; +\parallel off +drop table T1; +drop table T2; +drop table T3; +drop table T4; +drop table T5; +drop table T6; +drop table T7; +drop schema reindexinternal cascade; diff --git a/contrib/dolphin/expected/case_sensitive_test/role_test.out b/contrib/dolphin/expected/case_sensitive_test/role_test.out new file mode 100644 index 0000000000000000000000000000000000000000..67e78b002fde80666870c7d8e01d7c2b8ce1d281 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/role_test.out @@ -0,0 +1,33 @@ +DROP DATABASE IF EXISTS role_test_db; +NOTICE: database "role_test_db" does not exist, skipping +CREATE DATABASE role_test_db dbcompatibility 'b'; +\c role_test_db; +SET lower_case_table_names TO 0; +CREATE TABLE test_table (a int); +CREATE USER Test_User WITH PASSWORD 'openGauss@123'; +SELECT rolname FROM pg_roles WHERE rolname LIKE '%Test_%'; + rolname +----------- + Test_User +(1 row) + +GRANT ALL PRIVILEGES TO test_user; +ERROR: role "test_user" does not exist +REVOKE ALL PRIVILEGES FROM test_user; +ERROR: role "test_user" does not exist +GRANT ALL PRIVILEGES TO Test_User; +REVOKE ALL PRIVILEGES FROM Test_User; +ALTER USER test_user RENAME TO test_USer; +ERROR: role "test_user" does not exist +ALTER USER Test_User RENAME TO test_USer; +CREATE SCHEMA test_scheam AUTHORIZATION test_user; +ERROR: role "test_user" does not exist +CREATE SCHEMA test_scheam AUTHORIZATION test_USer; +ALTER TABLE test_table OWNER TO test_user; +ERROR: role "test_user" does not exist +ALTER TABLE test_table OWNER TO test_USer; +DROP USER test_user CASCADE; +ERROR: role "test_user" does not exist +DROP USER test_USer CASCADE; +\c postgres +DROP DATABASE role_test_db; diff --git a/contrib/dolphin/expected/case_sensitive_test/rowlevelsecurity.out b/contrib/dolphin/expected/case_sensitive_test/rowlevelsecurity.out new file mode 100644 index 0000000000000000000000000000000000000000..bc0fee6fd41158369b90a9f2fc7421c86cdc1613 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/rowlevelsecurity.out @@ -0,0 +1,1181 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- Test for Row Level Security feature +-- +-- initial setup +CREATE USER regress_rls_alice NOLOGIN PASSWORD 'Ttest@123'; +CREATE USER regress_rls_bob NOLOGIN PASSWORD 'Ttest@123'; +CREATE USER regress_rls_david NOLOGIN PASSWORD 'Ttest@123'; +CREATE USER regress_rls_peter NOLOGIN PASSWORD 'Ttest@123'; +CREATE USER regress_rls_single_user NOLOGIN PASSWORD 'Ttest@123'; +CREATE USER regress_rls_admin SYSADMIN NOLOGIN PASSWORD "Ttest@123"; +CREATE ROLE regress_rls_group1 NOLOGIN PASSWORD 'Ttest@123'; +CREATE ROLE regress_rls_group2 NOLOGIN PASSWORD 'Ttest@123'; +GRANT ALL on pg_roles to public; +GRANT ALL on pg_user to public; +GRANT regress_rls_group1 TO regress_rls_alice, regress_rls_bob, regress_rls_peter; +GRANT regress_rls_group2 TO regress_rls_david, regress_rls_peter, regress_rls_admin; +CREATE SCHEMA regress_rls_schema; +GRANT CREATE ON SCHEMA regress_rls_schema to public; +GRANT USAGE ON SCHEMA regress_rls_schema to public; +ALTER DATABASE regression ENABLE PRIVATE OBJECT; +ERROR: database "regression" does not exist +-- reconnect +\c +SET search_path = regress_rls_schema; +-- regress_rls_alice is the owner of all schema +SET ROLE regress_rls_alice PASSWORD 'Ttest@123'; +-- setup of malicious function (NOT SHIPPABLE) +CREATE OR REPLACE FUNCTION regress_rls_schema.rls_fleak1(text) RETURNS bool + COST 0.0000001 LANGUAGE plpgsql + AS 'BEGIN RAISE NOTICE ''f_leak => %'', $1; RETURN true; END'; +GRANT EXECUTE ON FUNCTION regress_rls_schema.rls_fleak1(text) TO public; +-- setup of malicious immutable function (SHIPPABLE) +CREATE OR REPLACE FUNCTION regress_rls_schema.rls_fleak2(text) RETURNS bool + COST 0.0000001 LANGUAGE plpgsql IMMUTABLE + AS 'BEGIN RAISE NOTICE ''f_leak => %'', $1; RETURN true; END'; +GRANT EXECUTE ON FUNCTION regress_rls_schema.rls_fleak2(text) TO public; +-- auto generate row level security policy +CREATE OR REPLACE FUNCTION regress_rls_schema.rls_auto_create_policy(t_name text, p_num int) +RETURNS INTEGER AS $$ +DECLARE + counter INTEGER := 1; + query text; +BEGIN + WHILE counter <= p_num LOOP + query := 'CREATE ROW LEVEL SECURITY POLICY ' || t_name || '_rls_' || counter || ' ON ' || t_name || ' USING(TRUE);'; + EXECUTE query; + counter := counter + 1; + END LOOP; + RETURN 1; +END; +$$language plpgsql; +REVOKE EXECUTE ON FUNCTION regress_rls_schema.rls_auto_create_policy(text, int) FROM public; +-- auto drop row level security policy +CREATE OR REPLACE FUNCTION regress_rls_schema.rls_auto_drop_policy(t_name text, p_num int) RETURNS INTEGER AS $$ +DECLARE + counter INTEGER := 1; + query text; +BEGIN + WHILE counter <= p_num LOOP + query := 'DROP ROW LEVEL SECURITY POLICY ' || t_name || '_rls_' || counter || ' ON ' || t_name; + EXECUTE query; + counter := counter + 1; + END LOOP; + RETURN 1; +END; +$$language plpgsql; +REVOKE EXECUTE ON FUNCTION regress_rls_schema.rls_auto_drop_policy(text, int) FROM public; +-- BASIC Row-Level Security Scenario +CREATE TABLE regress_rls_schema.account_row( + aid int, + aname varchar(100) +) WITH (ORIENTATION=row); +GRANT SELECT ON regress_rls_schema.account_row TO public; +INSERT INTO regress_rls_schema.account_row VALUES + (1, 'regress_rls_alice'), + (2, 'regress_rls_bob'), + (3, 'regress_rls_david'), + (4, 'regress_rls_peter'), + (5, 'regress_rls_admin'), + (6, 'regress_rls_single_user'); +ANALYZE regress_rls_schema.account_row; +CREATE TABLE regress_rls_schema.account_col( + aid int, + aname varchar(100) +) WITH (ORIENTATION=column); +GRANT SELECT ON regress_rls_schema.account_col TO public; +INSERT INTO regress_rls_schema.account_col SELECT * FROM regress_rls_schema.account_row; +ANALYZE regress_rls_schema.account_col; +CREATE TABLE regress_rls_schema.category_row( + cid int primary key, + cname text +) WITH (ORIENTATION=row); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "category_row_pkey" for table "category_row" +GRANT ALL ON regress_rls_schema.category_row TO public; +INSERT INTO regress_rls_schema.category_row VALUES + (11, 'novel'), + (22, 'science fiction'), + (33, 'technology'), + (44, 'manga'), + (55, 'biography'); +ANALYZE regress_rls_schema.category_row; +CREATE TABLE regress_rls_schema.category_col( + cid int, + cname text +) WITH (ORIENTATION=column); +GRANT ALL ON regress_rls_schema.category_col TO public; +INSERT INTO regress_rls_schema.category_col SELECT * FROM regress_rls_schema.category_row; +ANALYZE regress_rls_schema.category_col; +CREATE TABLE regress_rls_schema.document_row( + did int primary key, + cid int, + dlevel int not null, + dauthor name, + dtitle text +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "document_row_pkey" for table "document_row" +GRANT ALL ON regress_rls_schema.document_row TO public; +INSERT INTO regress_rls_schema.document_row VALUES + ( 1, 11, 1, 'regress_rls_bob', 'my first novel'), + ( 2, 11, 5, 'regress_rls_bob', 'my second novel'), + ( 3, 22, 7, 'regress_rls_bob', 'my science fiction'), + ( 4, 44, 9, 'regress_rls_bob', 'my first manga'), + ( 5, 44, 3, 'regress_rls_bob', 'my second manga'), + ( 6, 22, 2, 'regress_rls_peter', 'great science fiction'), + ( 7, 33, 6, 'regress_rls_peter', 'great technology book'), + ( 8, 44, 4, 'regress_rls_peter', 'great manga'), + ( 9, 22, 5, 'regress_rls_david', 'awesome science fiction'), + (10, 33, 4, 'regress_rls_david', 'awesome technology book'), + (11, 55, 8, 'regress_rls_alice', 'great biography'), + (12, 33, 10, 'regress_rls_admin', 'physical technology'), + (13, 55, 5, 'regress_rls_single_user', 'Beethoven biography'); +ANALYZE regress_rls_schema.document_row; +CREATE TABLE regress_rls_schema.document_col( + did int, + cid int, + dlevel int not null, + dauthor name, + dtitle text +); +GRANT ALL ON regress_rls_schema.document_col TO public; +INSERT INTO regress_rls_schema.document_col SELECT * FROM regress_rls_schema.document_row; +ANALYZE regress_rls_schema.document_col; +-- create partition table +CREATE TABLE par_row_t1 (id int, a int, b text)partition by range (a) +( + partition par_row_t1_p0 values less than(10), + partition par_row_t1_p1 values less than(50), + partition par_row_t1_p2 values less than(100), + partition par_row_t1_p3 values less than (maxvalue) +); +CREATE TABLE par_col_t1(id int, a int, b text) with(orientation = column) /*distribute by hash (id)*/ PARTITION BY RANGE (a) +( + partition par_col_t1_p0 values less than(10), + partition par_col_t1_p1 values less than(50), + partition par_col_t1_p2 values less than(100), + partition par_col_t1_p3 values less than (maxvalue) +); +INSERT INTO par_row_t1 VALUES (generate_series(1, 150) % 24, generate_series(1, 150), 'huawei'); +INSERT INTO par_col_t1 VALUES (generate_series(1, 150) % 24, generate_series(1, 150), 'huawei'); +GRANT SELECT ON par_row_t1 TO PUBLIC; +GRANT SELECT ON par_col_t1 TO PUBLIC; +CREATE ROW LEVEL SECURITY POLICY par_row_t1_rls1 ON par_row_t1 AS PERMISSIVE TO public USING(a <= 20); +CREATE ROW LEVEL SECURITY POLICY par_row_t1_rls2 ON par_row_t1 AS RESTRICTIVE TO regress_rls_group2 USING(id < 30); +CREATE ROW LEVEL SECURITY POLICY par_col_t1_rls1 ON par_col_t1 AS PERMISSIVE TO public USING(a <= 20); +CREATE ROW LEVEL SECURITY POLICY par_col_t1_rls2 ON par_col_t1 AS RESTRICTIVE TO regress_rls_group2 USING(id < 30); +ALTER TABLE par_row_t1 ENABLE ROW LEVEL SECURITY; +ALTER TABLE par_col_t1 ENABLE ROW LEVEL SECURITY; +-- create replication table +CREATE TABLE tt_rep(id int, name varchar(100)) /*DISTRIBUTE BY REPLICATION*/; +GRANT SELECT ON tt_rep TO PUBLIC; +INSERT INTO tt_rep VALUES (1, 'regress_rls_alice'), (2, 'regress_rls_david'), (3, 'regress_rls_peter'), (4, 'regress_rls_bob'); +ALTER TABLE tt_rep ENABLE ROW LEVEL SECURITY; +CREATE ROW LEVEL SECURITY POLICY tt_rep_rls1 ON tt_rep AS PERMISSIVE FOR SELECT TO regress_rls_group1 USING(name = current_user); +CREATE ROW LEVEL SECURITY POLICY tt_rep_rls2 ON tt_rep AS PERMISSIVE FOR SELECT TO regress_rls_group2 USING(id = 1); +-- create private table, test database private object +CREATE TABLE alice_private(id int, name varchar(100)); +CREATE TABLE alice_public_1(id int, name varchar(100)); +GRANT SELECT ON alice_public_1 TO regress_rls_group1; +CREATE TABLE alice_public_2(id int, name varchar(100)); +GRANT SELECT ON alice_public_2 TO regress_rls_group2; +-- create temp table +CREATE TEMP TABLE temp_tt(id int, name varchar(20)); +CREATE ROW LEVEL SECURITY POLICY temp_tt_rls ON temp_tt USING(id < 100); +ERROR: do not support row level security policy on temp table "temp_tt" +ALTER TABLE temp_tt ENABLE ROW LEVEL SECURITY; +ERROR: do not support row level security policy on temp table "temp_tt" +DROP TABLE temp_tt; +-- create 100 row level security policies on account_row +SELECT regress_rls_schema.rls_auto_create_policy('account_row', 100); + rls_auto_create_policy +------------------------ + 1 +(1 row) + +-- create 101 row level security policy on account_row, failed +CREATE ROW LEVEL SECURITY POLICY account_row_rls_101 ON regress_rls_schema.account_row USING(FALSE); +ERROR: Num of row level policies for relation should less than or equal to 100 +-- drop 100 row level security policies on account_row +SELECT regress_rls_schema.rls_auto_drop_policy('account_row', 100); + rls_auto_drop_policy +---------------------- + 1 +(1 row) + +-- create row level security policy on account_row, succeed +CREATE ROW LEVEL SECURITY POLICY account_row_rls_101 ON regress_rls_schema.account_row USING(FALSE); +-- drop row level security policy account_row_rls_101 for account_row +DROP ROW LEVEL SECURITY POLICY account_row_rls_101 ON regress_rls_schema.account_row; +SELECT count(*) FROM pg_catalog.pg_rlspolicies where tablename = 'account_row'; + count +------- + 0 +(1 row) + +-- enable row level security for document_row, document_col +ALTER TABLE regress_rls_schema.document_row ENABLE ROW LEVEL SECURITY; +ALTER TABLE regress_rls_schema.document_col ENABLE ROW LEVEL SECURITY; +-- user's security level must be higher than or equal to document's +CREATE ROW LEVEL SECURITY POLICY p01 ON document_row AS PERMISSIVE + USING (dlevel <= (SELECT aid FROM account_row WHERE aname = current_user)); +CREATE ROW LEVEL SECURITY POLICY p01 ON document_col AS PERMISSIVE + USING (dlevel <= (SELECT aid FROM account_col WHERE aname = current_user)); +-- try to create a policy of wrong type +CREATE ROW LEVEL SECURITY POLICY p02 ON document_row AS WHATEVER + USING (dlevel <= (SELECT aid FROM account_row WHERE aname = current_user)); +ERROR: unrecognized row security option "whatever" +LINE 1: ...TE ROW LEVEL SECURITY POLICY p02 ON document_row AS WHATEVER + ^ +HINT: Only PERMISSIVE or RESTRICTIVE policies are supported currently. +-- regress_rls_david isn't allowed to anything at cid 50 or above +-- this is to make sure that we sort the policies by name first +CREATE ROW LEVEL SECURITY POLICY p02 ON document_row AS RESTRICTIVE TO regress_rls_david + USING (cid < 50); +CREATE ROW LEVEL SECURITY POLICY p02 ON document_col AS RESTRICTIVE TO regress_rls_david + USING (cid < 50); +-- and regress_rls_david isn't allowed to see manga documents +CREATE ROW LEVEL SECURITY POLICY p03 ON document_row AS RESTRICTIVE TO regress_rls_david + USING (cid <> 44); +CREATE ROW LEVEL SECURITY POLICY p03 ON document_col AS RESTRICTIVE TO regress_rls_david + USING (cid <> 44); +-- policy for update/delete +CREATE ROW LEVEL SECURITY POLICY p04 ON document_row AS RESTRICTIVE FOR UPDATE TO regress_rls_bob, regress_rls_david USING ((dlevel % 2) = 1); +CREATE ROW LEVEL SECURITY POLICY p05 ON document_row AS RESTRICTIVE FOR DELETE TO regress_rls_bob, regress_rls_david USING ((dlevel % 2) = 0); +-- policy for regress_rls_bob +CREATE ROW LEVEL SECURITY POLICY p06 ON document_row AS RESTRICTIVE FOR SELECT TO regress_rls_bob USING ((dlevel % 2) = 1); +\d + List of relations + Schema | Name | Type | Owner | Storage +--------------------+----------------+-------+-------------------+-------------------------------------------------------------- + regress_rls_schema | account_col | table | regress_rls_alice | {orientation=column,compression=low} + regress_rls_schema | account_row | table | regress_rls_alice | {orientation=row,compression=no} + regress_rls_schema | alice_private | table | regress_rls_alice | {orientation=row,compression=no} + regress_rls_schema | alice_public_1 | table | regress_rls_alice | {orientation=row,compression=no} + regress_rls_schema | alice_public_2 | table | regress_rls_alice | {orientation=row,compression=no} + regress_rls_schema | category_col | table | regress_rls_alice | {orientation=column,compression=low} + regress_rls_schema | category_row | table | regress_rls_alice | {orientation=row,compression=no} + regress_rls_schema | document_col | table | regress_rls_alice | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | document_row | table | regress_rls_alice | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | par_col_t1 | table | regress_rls_alice | {orientation=column,compression=low,enable_rowsecurity=true} + regress_rls_schema | par_row_t1 | table | regress_rls_alice | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | tt_rep | table | regress_rls_alice | {orientation=row,compression=no,enable_rowsecurity=true} +(12 rows) + +\d+ "document_row" + Table "regress_rls_schema.document_row" + Column | Type | Modifiers | Storage | Stats target | Description +---------+---------+-----------+----------+--------------+------------- + did | integer | not null | plain | | + cid | integer | | plain | | + dlevel | integer | not null | plain | | + dauthor | name | | plain | | + dtitle | text | | extended | | +Indexes: + "document_row_pkey" PRIMARY KEY, btree (did) TABLESPACE pg_default +Row Level Security Policies: + POLICY "p01" FOR ALL + TO {public} + USING ((dlevel <= (SELECT account_row.aid FROM account_row WHERE ((account_row.aname)::name = "current_user"())))) + POLICY "p02" AS RESTRICTIVE FOR ALL + TO {regress_rls_david} + USING ((cid < 50)) + POLICY "p03" AS RESTRICTIVE FOR ALL + TO {regress_rls_david} + USING ((cid <> 44)) + POLICY "p04" AS RESTRICTIVE FOR UPDATE + TO {regress_rls_bob,regress_rls_david} + USING (((dlevel % 2) = 1)) + POLICY "p05" AS RESTRICTIVE FOR DELETE + TO {regress_rls_bob,regress_rls_david} + USING (((dlevel % 2) = 0)) + POLICY "p06" AS RESTRICTIVE FOR SELECT + TO {regress_rls_bob} + USING (((dlevel % 2) = 1)) +Has OIDs: no +Options: orientation=row, compression=no, enable_rowsecurity=true + +SELECT * FROM pg_rlspolicies WHERE schemaname = 'regress_rls_schema' AND tablename = 'document_row' ORDER BY policyname; + schemaname | tablename | policyname | policypermissive | policyroles | policycmd | policyqual +--------------------+--------------+------------+------------------+-------------------------------------+-----------+------------------------------------------------------------------------------------------------------------ + regress_rls_schema | document_row | p01 | PERMISSIVE | {public} | ALL | (dlevel <= (SELECT account_row.aid FROM account_row WHERE ((account_row.aname)::name = "current_user"()))) + regress_rls_schema | document_row | p02 | RESTRICTIVE | {regress_rls_david} | ALL | (cid < 50) + regress_rls_schema | document_row | p03 | RESTRICTIVE | {regress_rls_david} | ALL | (cid <> 44) + regress_rls_schema | document_row | p04 | RESTRICTIVE | {regress_rls_bob,regress_rls_david} | UPDATE | ((dlevel % 2) = 1) + regress_rls_schema | document_row | p05 | RESTRICTIVE | {regress_rls_bob,regress_rls_david} | DELETE | ((dlevel % 2) = 0) + regress_rls_schema | document_row | p06 | RESTRICTIVE | {regress_rls_bob} | SELECT | ((dlevel % 2) = 1) +(6 rows) + +-- prepare statement +PREPARE one AS SELECT * FROM document_row ORDER BY 1; +PREPARE two AS SELECT * FROM document_col ORDER BY 1; +EXECUTE one; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------------+------------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 2 | 11 | 5 | regress_rls_bob | my second novel + 3 | 22 | 7 | regress_rls_bob | my science fiction + 4 | 44 | 9 | regress_rls_bob | my first manga + 5 | 44 | 3 | regress_rls_bob | my second manga + 6 | 22 | 2 | regress_rls_peter | great science fiction + 7 | 33 | 6 | regress_rls_peter | great technology book + 8 | 44 | 4 | regress_rls_peter | great manga + 9 | 22 | 5 | regress_rls_david | awesome science fiction + 10 | 33 | 4 | regress_rls_david | awesome technology book + 11 | 55 | 8 | regress_rls_alice | great biography + 12 | 33 | 10 | regress_rls_admin | physical technology + 13 | 55 | 5 | regress_rls_single_user | Beethoven biography +(13 rows) + +EXECUTE one; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------------+------------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 2 | 11 | 5 | regress_rls_bob | my second novel + 3 | 22 | 7 | regress_rls_bob | my science fiction + 4 | 44 | 9 | regress_rls_bob | my first manga + 5 | 44 | 3 | regress_rls_bob | my second manga + 6 | 22 | 2 | regress_rls_peter | great science fiction + 7 | 33 | 6 | regress_rls_peter | great technology book + 8 | 44 | 4 | regress_rls_peter | great manga + 9 | 22 | 5 | regress_rls_david | awesome science fiction + 10 | 33 | 4 | regress_rls_david | awesome technology book + 11 | 55 | 8 | regress_rls_alice | great biography + 12 | 33 | 10 | regress_rls_admin | physical technology + 13 | 55 | 5 | regress_rls_single_user | Beethoven biography +(13 rows) + +EXECUTE two; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------------+------------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 2 | 11 | 5 | regress_rls_bob | my second novel + 3 | 22 | 7 | regress_rls_bob | my science fiction + 4 | 44 | 9 | regress_rls_bob | my first manga + 5 | 44 | 3 | regress_rls_bob | my second manga + 6 | 22 | 2 | regress_rls_peter | great science fiction + 7 | 33 | 6 | regress_rls_peter | great technology book + 8 | 44 | 4 | regress_rls_peter | great manga + 9 | 22 | 5 | regress_rls_david | awesome science fiction + 10 | 33 | 4 | regress_rls_david | awesome technology book + 11 | 55 | 8 | regress_rls_alice | great biography + 12 | 33 | 10 | regress_rls_admin | physical technology + 13 | 55 | 5 | regress_rls_single_user | Beethoven biography +(13 rows) + +EXECUTE two; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------------+------------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 2 | 11 | 5 | regress_rls_bob | my second novel + 3 | 22 | 7 | regress_rls_bob | my science fiction + 4 | 44 | 9 | regress_rls_bob | my first manga + 5 | 44 | 3 | regress_rls_bob | my second manga + 6 | 22 | 2 | regress_rls_peter | great science fiction + 7 | 33 | 6 | regress_rls_peter | great technology book + 8 | 44 | 4 | regress_rls_peter | great manga + 9 | 22 | 5 | regress_rls_david | awesome science fiction + 10 | 33 | 4 | regress_rls_david | awesome technology book + 11 | 55 | 8 | regress_rls_alice | great biography + 12 | 33 | 10 | regress_rls_admin | physical technology + 13 | 55 | 5 | regress_rls_single_user | Beethoven biography +(13 rows) + +-- viewpoint from regress_rls_bob +SET ROLE regress_rls_bob PASSWORD 'Ttest@123'; +EXECUTE one; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-----------------+---------------- + 1 | 11 | 1 | regress_rls_bob | my first novel +(1 row) + +EXECUTE two; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+----------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 6 | 22 | 2 | regress_rls_peter | great science fiction +(2 rows) + +SELECT * FROM document_row WHERE rls_fleak1(dtitle) ORDER BY did; +NOTICE: f_leak => my first novel + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-----------------+---------------- + 1 | 11 | 1 | regress_rls_bob | my first novel +(1 row) + +SELECT * FROM document_col WHERE rls_fleak2(dauthor) ORDER BY did; +NOTICE: f_leak => regress_rls_bob +NOTICE: f_leak => regress_rls_peter + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+----------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 6 | 22 | 2 | regress_rls_peter | great science fiction +(2 rows) + +-- EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row WHERE rls_fleak2(dauthor) ORDER BY did; +SELECT * FROM document_col INNER JOIN category_col ON document_col.cid=category_col.cid WHERE rls_fleak1(dtitle) ORDER BY did; +NOTICE: f_leak => my first novel +NOTICE: f_leak => great science fiction + did | cid | dlevel | dauthor | dtitle | cid | cname +-----+-----+--------+-------------------+-----------------------+-----+----------------- + 1 | 11 | 1 | regress_rls_bob | my first novel | 11 | novel + 6 | 22 | 2 | regress_rls_peter | great science fiction | 22 | science fiction +(2 rows) + +SELECT * FROM tt_rep; + id | name +----+----------------- + 4 | regress_rls_bob +(1 row) + +SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; +NOTICE: f_leak => regress_rls_bob + did | cid | dlevel | dauthor | dtitle | cid | cname +-----+-----+--------+-----------------+----------------+-----+------- + 1 | 11 | 1 | regress_rls_bob | my first novel | 11 | novel +(1 row) + +-- EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; +\d + List of relations + Schema | Name | Type | Owner | Storage +--------------------+----------------+-------+-------+-------------------------------------------------------------- + regress_rls_schema | account_col | table | | {orientation=column,compression=low} + regress_rls_schema | account_row | table | | {orientation=row,compression=no} + regress_rls_schema | alice_private | table | | {orientation=row,compression=no} + regress_rls_schema | alice_public_1 | table | | {orientation=row,compression=no} + regress_rls_schema | alice_public_2 | table | | {orientation=row,compression=no} + regress_rls_schema | category_col | table | | {orientation=column,compression=low} + regress_rls_schema | category_row | table | | {orientation=row,compression=no} + regress_rls_schema | document_col | table | | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | document_row | table | | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | par_col_t1 | table | | {orientation=column,compression=low,enable_rowsecurity=true} + regress_rls_schema | par_row_t1 | table | | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | tt_rep | table | | {orientation=row,compression=no,enable_rowsecurity=true} +(12 rows) + +\df + List of functions + Schema | Name | Result data type | Argument data types | Type | fencedmode | propackage | prokind +--------------------+------------------------+------------------+----------------------------+--------+------------+------------+--------- + regress_rls_schema | rls_auto_create_policy | integer | t_name text, p_num integer | normal | f | f | f + regress_rls_schema | rls_auto_drop_policy | integer | t_name text, p_num integer | normal | f | f | f + regress_rls_schema | rls_fleak1 | boolean | text | normal | f | f | f + regress_rls_schema | rls_fleak2 | boolean | text | normal | f | f | f +(4 rows) + +-- viewpoint from regress_rls_peter +SET ROLE regress_rls_peter PASSWORD 'Ttest@123'; +EXECUTE one; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+------------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 5 | 44 | 3 | regress_rls_bob | my second manga + 6 | 22 | 2 | regress_rls_peter | great science fiction + 8 | 44 | 4 | regress_rls_peter | great manga + 10 | 33 | 4 | regress_rls_david | awesome technology book +(5 rows) + +EXECUTE two; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+------------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 5 | 44 | 3 | regress_rls_bob | my second manga + 6 | 22 | 2 | regress_rls_peter | great science fiction + 8 | 44 | 4 | regress_rls_peter | great manga + 10 | 33 | 4 | regress_rls_david | awesome technology book +(5 rows) + +SELECT * FROM document_row WHERE rls_fleak1(dtitle) ORDER BY did; +NOTICE: f_leak => my first novel +NOTICE: f_leak => my second manga +NOTICE: f_leak => great science fiction +NOTICE: f_leak => great manga +NOTICE: f_leak => awesome technology book + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+------------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 5 | 44 | 3 | regress_rls_bob | my second manga + 6 | 22 | 2 | regress_rls_peter | great science fiction + 8 | 44 | 4 | regress_rls_peter | great manga + 10 | 33 | 4 | regress_rls_david | awesome technology book +(5 rows) + +SELECT * FROM document_col WHERE rls_fleak2(dauthor) ORDER BY did; +NOTICE: f_leak => regress_rls_bob +NOTICE: f_leak => regress_rls_bob +NOTICE: f_leak => regress_rls_peter +NOTICE: f_leak => regress_rls_peter +NOTICE: f_leak => regress_rls_david + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+------------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 5 | 44 | 3 | regress_rls_bob | my second manga + 6 | 22 | 2 | regress_rls_peter | great science fiction + 8 | 44 | 4 | regress_rls_peter | great manga + 10 | 33 | 4 | regress_rls_david | awesome technology book +(5 rows) + +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row WHERE rls_fleak2(dauthor) ORDER BY did; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Sort + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle + Sort Key: document_row.did + InitPlan 1 (returns $0) + -> Seq Scan on regress_rls_schema.account_row + Output: account_row.aid + Filter: ((account_row.aname)::name = 'regress_rls_peter'::name) + -> Seq Scan on regress_rls_schema.document_row + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle + Filter: ((document_row.dlevel <= $0) AND rls_fleak2((document_row.dauthor)::text)) + Notice: This query is influenced by row level security feature +(11 rows) + +SELECT * FROM document_col INNER JOIN category_col ON document_col.cid=category_col.cid WHERE rls_fleak1(dtitle) ORDER BY did; +NOTICE: f_leak => my first novel +NOTICE: f_leak => my second manga +NOTICE: f_leak => great science fiction +NOTICE: f_leak => great manga +NOTICE: f_leak => awesome technology book + did | cid | dlevel | dauthor | dtitle | cid | cname +-----+-----+--------+-------------------+-------------------------+-----+----------------- + 1 | 11 | 1 | regress_rls_bob | my first novel | 11 | novel + 5 | 44 | 3 | regress_rls_bob | my second manga | 44 | manga + 6 | 22 | 2 | regress_rls_peter | great science fiction | 22 | science fiction + 8 | 44 | 4 | regress_rls_peter | great manga | 44 | manga + 10 | 33 | 4 | regress_rls_david | awesome technology book | 33 | technology +(5 rows) + +SELECT * FROM tt_rep; + id | name +----+------------------- + 1 | regress_rls_alice + 3 | regress_rls_peter +(2 rows) + +SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; +NOTICE: f_leak => regress_rls_bob +NOTICE: f_leak => regress_rls_bob +NOTICE: f_leak => regress_rls_peter +NOTICE: f_leak => regress_rls_peter +NOTICE: f_leak => regress_rls_david + did | cid | dlevel | dauthor | dtitle | cid | cname +-----+-----+--------+-------------------+-------------------------+-----+----------------- + 1 | 11 | 1 | regress_rls_bob | my first novel | 11 | novel + 5 | 44 | 3 | regress_rls_bob | my second manga | 44 | manga + 6 | 22 | 2 | regress_rls_peter | great science fiction | 22 | science fiction + 8 | 44 | 4 | regress_rls_peter | great manga | 44 | manga + 10 | 33 | 4 | regress_rls_david | awesome technology book | 33 | technology +(5 rows) + +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; + QUERY PLAN +---------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle, category_row.cid, category_row.cname + Sort Key: document_row.did + InitPlan 1 (returns $0) + -> Seq Scan on regress_rls_schema.account_row + Output: account_row.aid + Filter: ((account_row.aname)::name = 'regress_rls_peter'::name) + -> Hash Join + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle, category_row.cid, category_row.cname + Hash Cond: (category_row.cid = document_row.cid) + -> Seq Scan on regress_rls_schema.category_row + Output: category_row.cid, category_row.cname + -> Hash + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle + -> Seq Scan on regress_rls_schema.document_row + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle + Filter: ((document_row.dlevel <= $0) AND rls_fleak2((document_row.dauthor)::text)) + Notice: This query is influenced by row level security feature +(18 rows) + +-- viewpoint from regress_rls_david +SET ROLE regress_rls_david PASSWORD 'Ttest@123'; +EXECUTE one; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+----------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 6 | 22 | 2 | regress_rls_peter | great science fiction +(2 rows) + +EXECUTE two; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+----------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 6 | 22 | 2 | regress_rls_peter | great science fiction +(2 rows) + +SELECT * FROM document_row WHERE rls_fleak1(dtitle) ORDER BY did; +NOTICE: f_leak => my first novel +NOTICE: f_leak => great science fiction + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+----------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 6 | 22 | 2 | regress_rls_peter | great science fiction +(2 rows) + +SELECT * FROM document_col WHERE rls_fleak2(dauthor) ORDER BY did; +NOTICE: f_leak => regress_rls_bob +NOTICE: f_leak => regress_rls_peter + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+----------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 6 | 22 | 2 | regress_rls_peter | great science fiction +(2 rows) + +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row ORDER BY did; + QUERY PLAN +-------------------------------------------------------------------------------------------------------------------- + Sort + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle + Sort Key: document_row.did + InitPlan 1 (returns $0) + -> Seq Scan on regress_rls_schema.account_row + Output: account_row.aid + Filter: ((account_row.aname)::name = 'regress_rls_david'::name) + -> Seq Scan on regress_rls_schema.document_row + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle + Filter: ((document_row.cid < 50) AND (document_row.cid <> 44) AND (document_row.dlevel <= $0)) + Notice: This query is influenced by row level security feature +(11 rows) + +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row WHERE rls_fleak2(dauthor) ORDER BY did; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle + Sort Key: document_row.did + InitPlan 1 (returns $0) + -> Seq Scan on regress_rls_schema.account_row + Output: account_row.aid + Filter: ((account_row.aname)::name = 'regress_rls_david'::name) + -> Seq Scan on regress_rls_schema.document_row + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle + Filter: ((document_row.cid < 50) AND (document_row.cid <> 44) AND (document_row.dlevel <= $0) AND rls_fleak2((document_row.dauthor)::text)) + Notice: This query is influenced by row level security feature +(11 rows) + +SELECT * FROM document_col INNER JOIN category_col ON document_col.cid=category_col.cid WHERE rls_fleak1(dtitle) ORDER BY did; +NOTICE: f_leak => my first novel +NOTICE: f_leak => great science fiction + did | cid | dlevel | dauthor | dtitle | cid | cname +-----+-----+--------+-------------------+-----------------------+-----+----------------- + 1 | 11 | 1 | regress_rls_bob | my first novel | 11 | novel + 6 | 22 | 2 | regress_rls_peter | great science fiction | 22 | science fiction +(2 rows) + +SELECT * FROM tt_rep; + id | name +----+------------------- + 1 | regress_rls_alice +(1 row) + +COPY document_row TO STDOUT; +1 11 1 regress_rls_bob my first novel +6 22 2 regress_rls_peter great science fiction +COPY document_col TO STDOUT; +1 11 1 regress_rls_bob my first novel +6 22 2 regress_rls_peter great science fiction +SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; +NOTICE: f_leak => regress_rls_bob +NOTICE: f_leak => regress_rls_peter + did | cid | dlevel | dauthor | dtitle | cid | cname +-----+-----+--------+-------------------+-----------------------+-----+----------------- + 1 | 11 | 1 | regress_rls_bob | my first novel | 11 | novel + 6 | 22 | 2 | regress_rls_peter | great science fiction | 22 | science fiction +(2 rows) + +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; + QUERY PLAN +----------------------------------------------------------------------------------------------------------------------------------------------------------- + Sort + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle, category_row.cid, category_row.cname + Sort Key: document_row.did + InitPlan 1 (returns $0) + -> Seq Scan on regress_rls_schema.account_row + Output: account_row.aid + Filter: ((account_row.aname)::name = 'regress_rls_david'::name) + -> Nested Loop + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle, category_row.cid, category_row.cname + Join Filter: (document_row.cid = category_row.cid) + -> Seq Scan on regress_rls_schema.document_row + Output: document_row.did, document_row.cid, document_row.dlevel, document_row.dauthor, document_row.dtitle + Filter: ((document_row.cid < 50) AND (document_row.cid <> 44) AND (document_row.dlevel <= $0) AND rls_fleak2((document_row.dauthor)::text)) + -> Seq Scan on regress_rls_schema.category_row + Output: category_row.cid, category_row.cname + Filter: ((category_row.cid < 50) AND (category_row.cid <> 44)) + Notice: This query is influenced by row level security feature +(17 rows) + +-- update and update returning +UPDATE document_row SET dlevel = dlevel + 1 - 1 WHERE did > 1; +UPDATE document_col SET dlevel = dlevel + 1 - 1 WHERE did > 1 RETURNING dauthor, did; + dauthor | did +-------------------+----- + regress_rls_peter | 6 +(1 row) + +-- delete and delete returning +INSERT INTO document_row VALUES (100, 49, 1, 'regress_rls_david', 'testing sorting of policies'); +DELETE FROM document_row WHERE did = 100; +INSERT INTO document_row VALUES (100, 49, 1, 'regress_rls_david', 'testing sorting of policies'); +ERROR: duplicate key value violates unique constraint "document_row_pkey" +DETAIL: Key (did)=(100) already exists. +DELETE FROM document_row WHERE did = 100 RETURNING dauthor, did; + dauthor | did +---------+----- +(0 rows) + +-- only owner can change policies +ALTER POLICY p01 ON document_row USING (true); --fail +ERROR: must be owner of relation document_row +DETAIL: N/A +DROP POLICY p01 ON document_col; --fail +ERROR: must be owner of relation document_col +DETAIL: N/A +-- check data from partition table +SELECT * FROM par_row_t1 WHERE a > 7 ORDER BY 1, 2; + id | a | b +----+----+-------- + 8 | 8 | huawei + 9 | 9 | huawei + 10 | 10 | huawei + 11 | 11 | huawei + 12 | 12 | huawei + 13 | 13 | huawei + 14 | 14 | huawei + 15 | 15 | huawei + 16 | 16 | huawei + 17 | 17 | huawei + 18 | 18 | huawei + 19 | 19 | huawei + 20 | 20 | huawei +(13 rows) + +SELECT * FROM par_col_t1 WHERE a > 7 ORDER BY 1, 2; + id | a | b +----+----+-------- + 8 | 8 | huawei + 9 | 9 | huawei + 10 | 10 | huawei + 11 | 11 | huawei + 12 | 12 | huawei + 13 | 13 | huawei + 14 | 14 | huawei + 15 | 15 | huawei + 16 | 16 | huawei + 17 | 17 | huawei + 18 | 18 | huawei + 19 | 19 | huawei + 20 | 20 | huawei +(13 rows) + +-- test create table as +CREATE TABLE document_row_david AS SELECT * FROM document_row; +SELECT COUNT(*) FROM document_row_david; + count +------- + 3 +(1 row) + +-- check table and functions +\d + List of relations + Schema | Name | Type | Owner | Storage +--------------------+--------------------+-------+-------------------+-------------------------------------------------------------- + regress_rls_schema | account_col | table | | {orientation=column,compression=low} + regress_rls_schema | account_row | table | | {orientation=row,compression=no} + regress_rls_schema | alice_private | table | | {orientation=row,compression=no} + regress_rls_schema | alice_public_1 | table | | {orientation=row,compression=no} + regress_rls_schema | alice_public_2 | table | | {orientation=row,compression=no} + regress_rls_schema | category_col | table | | {orientation=column,compression=low} + regress_rls_schema | category_row | table | | {orientation=row,compression=no} + regress_rls_schema | document_col | table | | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | document_row | table | | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | document_row_david | table | regress_rls_david | {orientation=row,compression=no} + regress_rls_schema | par_col_t1 | table | | {orientation=column,compression=low,enable_rowsecurity=true} + regress_rls_schema | par_row_t1 | table | | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | tt_rep | table | | {orientation=row,compression=no,enable_rowsecurity=true} +(13 rows) + +\df + List of functions + Schema | Name | Result data type | Argument data types | Type | fencedmode | propackage | prokind +--------------------+------------------------+------------------+----------------------------+--------+------------+------------+--------- + regress_rls_schema | rls_auto_create_policy | integer | t_name text, p_num integer | normal | f | f | f + regress_rls_schema | rls_auto_drop_policy | integer | t_name text, p_num integer | normal | f | f | f + regress_rls_schema | rls_fleak1 | boolean | text | normal | f | f | f + regress_rls_schema | rls_fleak2 | boolean | text | normal | f | f | f +(4 rows) + +-- change to super user +RESET ROLE; +-- DROP USER failed, display dependency +DROP USER regress_rls_bob; +ERROR: role "regress_rls_bob" cannot be dropped because some objects depend on it +DETAIL: target of row level security policy p06 on table document_row +target of row level security policy p05 on table document_row +target of row level security policy p04 on table document_row +DROP OWNED BY regress_rls_bob; +select * from pg_shdepend where classid = 3254 and refclassid = 1260 and refobjid = (select oid from pg_authid where rolname = 'regress_rls_bob'); + dbid | classid | objid | objsubid | refclassid | refobjid | deptype | objfile +------+---------+-------+----------+------------+----------+---------+--------- +(0 rows) + +DROP USER regress_rls_bob; +ALTER POLICY p01 ON document_row USING (dauthor = current_user); +ALTER POLICY p01 ON document_row RENAME TO p12; +ALTER POLICY p12 ON document_row RENAME TO p13; +ALTER POLICY p13 ON document_row RENAME TO p01; +SELECT * FROM pg_rlspolicies ORDER BY tablename, policyname; + schemaname | tablename | policyname | policypermissive | policyroles | policycmd | policyqual +--------------------+--------------+-----------------+------------------+----------------------+-----------+------------------------------------------------------------------------------------------------------------ + regress_rls_schema | document_col | p01 | PERMISSIVE | {public} | ALL | (dlevel <= (SELECT account_col.aid FROM account_col WHERE ((account_col.aname)::name = "current_user"()))) + regress_rls_schema | document_col | p02 | RESTRICTIVE | {regress_rls_david} | ALL | (cid < 50) + regress_rls_schema | document_col | p03 | RESTRICTIVE | {regress_rls_david} | ALL | (cid <> 44) + regress_rls_schema | document_row | p01 | PERMISSIVE | {public} | ALL | (dauthor = "current_user"()) + regress_rls_schema | document_row | p02 | RESTRICTIVE | {regress_rls_david} | ALL | (cid < 50) + regress_rls_schema | document_row | p03 | RESTRICTIVE | {regress_rls_david} | ALL | (cid <> 44) + regress_rls_schema | document_row | p04 | RESTRICTIVE | {regress_rls_david} | UPDATE | ((dlevel % 2) = 1) + regress_rls_schema | document_row | p05 | RESTRICTIVE | {regress_rls_david} | DELETE | ((dlevel % 2) = 0) + regress_rls_schema | par_col_t1 | par_col_t1_rls1 | PERMISSIVE | {public} | ALL | (a <= 20) + regress_rls_schema | par_col_t1 | par_col_t1_rls2 | RESTRICTIVE | {regress_rls_group2} | ALL | (id < 30) + regress_rls_schema | par_row_t1 | par_row_t1_rls1 | PERMISSIVE | {public} | ALL | (a <= 20) + regress_rls_schema | par_row_t1 | par_row_t1_rls2 | RESTRICTIVE | {regress_rls_group2} | ALL | (id < 30) + regress_rls_schema | tt_rep | tt_rep_rls1 | PERMISSIVE | {regress_rls_group1} | SELECT | ((name)::name = "current_user"()) + regress_rls_schema | tt_rep | tt_rep_rls2 | PERMISSIVE | {regress_rls_group2} | SELECT | (id = 1) +(14 rows) + +-- enable private object +ALTER DATABASE regression DISABLE PRIVATE OBJECT; +ERROR: database "regression" does not exist +-- reconnect +\c +SET search_path = regress_rls_schema; +-- check audit logs +SELECT type, database, object_name, detail_info FROM pg_query_audit('2000-01-01 00:00:00', '2100-01-01 00:00:00') + WHERE detail_info LIKE '%private object%' OR detail_info LIKE '%PRIVATE OBJECT%' ORDER BY detail_info; + type | database | object_name | detail_info +------+----------+-------------+------------- +(0 rows) + +-- viewpoint from rls_regres_david again +SET ROLE regress_rls_david PASSWORD 'Ttest@123'; +SELECT * FROM document_row ORDER BY did; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+----------------------------- + 9 | 22 | 5 | regress_rls_david | awesome science fiction + 10 | 33 | 4 | regress_rls_david | awesome technology book + 100 | 49 | 1 | regress_rls_david | testing sorting of policies +(3 rows) + +SELECT * FROM document_col ORDER BY did; + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+----------------------- + 1 | 11 | 1 | regress_rls_bob | my first novel + 6 | 22 | 2 | regress_rls_peter | great science fiction +(2 rows) + +SELECT * FROM document_row WHERE rls_fleak1(dtitle) ORDER BY did; +NOTICE: f_leak => awesome science fiction +NOTICE: f_leak => awesome technology book +NOTICE: f_leak => testing sorting of policies + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+----------------------------- + 9 | 22 | 5 | regress_rls_david | awesome science fiction + 10 | 33 | 4 | regress_rls_david | awesome technology book + 100 | 49 | 1 | regress_rls_david | testing sorting of policies +(3 rows) + +SELECT * FROM document_row WHERE rls_fleak2(dtitle) ORDER BY did; +NOTICE: f_leak => awesome science fiction +NOTICE: f_leak => awesome technology book +NOTICE: f_leak => testing sorting of policies + did | cid | dlevel | dauthor | dtitle +-----+-----+--------+-------------------+----------------------------- + 9 | 22 | 5 | regress_rls_david | awesome science fiction + 10 | 33 | 4 | regress_rls_david | awesome technology book + 100 | 49 | 1 | regress_rls_david | testing sorting of policies +(3 rows) + +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row WHERE rls_fleak2(dtitle); + QUERY PLAN +------------------------------------------------------------------------------------------------------------------------------------------------------------- + Seq Scan on regress_rls_schema.document_row + Output: did, cid, dlevel, dauthor, dtitle + Filter: ((document_row.cid < 50) AND (document_row.cid <> 44) AND (document_row.dauthor = 'regress_rls_david'::name) AND rls_fleak2(document_row.dtitle)) + Notice: This query is influenced by row level security feature +(4 rows) + +SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dtitle) ORDER by did; +NOTICE: f_leak => awesome science fiction +NOTICE: f_leak => awesome technology book +NOTICE: f_leak => testing sorting of policies + did | cid | dlevel | dauthor | dtitle | cid | cname +-----+-----+--------+-------------------+-------------------------+-----+----------------- + 9 | 22 | 5 | regress_rls_david | awesome science fiction | 22 | science fiction + 10 | 33 | 4 | regress_rls_david | awesome technology book | 33 | technology +(2 rows) + +-- test inlist +SET qrw_inlist2join_optmode=1; +CREATE TABLE inlist_t1(c1 int, c2 int, c3 int) /*DISTRIBUTE BY HASH(c1)*/; +INSERT INTO inlist_t1 SELECT v,v,v FROM generate_series(1,12) as v; +CREATE ROW LEVEL SECURITY POLICY inlist_t1_rls ON inlist_t1 USING(c3 IN (3,4,7)); +ALTER TABLE inlist_t1 ENABLE ROW LEVEL SECURITY; +ALTER TABLE inlist_t1 FORCE ROW LEVEL SECURITY; +SELECT * FROM inlist_t1 ORDER BY c1; + c1 | c2 | c3 +----+----+---- + 3 | 3 | 3 + 4 | 4 | 4 + 7 | 7 | 7 +(3 rows) + +RESET qrw_inlist2join_optmode; +-- check data from partition table +SELECT * FROM par_row_t1 WHERE a > 7 ORDER BY 1, 2; + id | a | b +----+----+-------- + 8 | 8 | huawei + 9 | 9 | huawei + 10 | 10 | huawei + 11 | 11 | huawei + 12 | 12 | huawei + 13 | 13 | huawei + 14 | 14 | huawei + 15 | 15 | huawei + 16 | 16 | huawei + 17 | 17 | huawei + 18 | 18 | huawei + 19 | 19 | huawei + 20 | 20 | huawei +(13 rows) + +SELECT * FROM par_col_t1 WHERE a > 7 ORDER BY 1, 2; + id | a | b +----+----+-------- + 8 | 8 | huawei + 9 | 9 | huawei + 10 | 10 | huawei + 11 | 11 | huawei + 12 | 12 | huawei + 13 | 13 | huawei + 14 | 14 | huawei + 15 | 15 | huawei + 16 | 16 | huawei + 17 | 17 | huawei + 18 | 18 | huawei + 19 | 19 | huawei + 20 | 20 | huawei +(13 rows) + +SELECT * FROM tt_rep; + id | name +----+------------------- + 1 | regress_rls_alice +(1 row) + +-- check table and functions +\d + List of relations + Schema | Name | Type | Owner | Storage +--------------------+--------------------+-------+-------------------+--------------------------------------------------------------------------------- + regress_rls_schema | account_col | table | | {orientation=column,compression=low} + regress_rls_schema | account_row | table | | {orientation=row,compression=no} + regress_rls_schema | alice_private | table | | {orientation=row,compression=no} + regress_rls_schema | alice_public_1 | table | | {orientation=row,compression=no} + regress_rls_schema | alice_public_2 | table | | {orientation=row,compression=no} + regress_rls_schema | category_col | table | | {orientation=column,compression=low} + regress_rls_schema | category_row | table | | {orientation=row,compression=no} + regress_rls_schema | document_col | table | | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | document_row | table | | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | document_row_david | table | regress_rls_david | {orientation=row,compression=no} + regress_rls_schema | inlist_t1 | table | regress_rls_david | {orientation=row,compression=no,enable_rowsecurity=true,force_rowsecurity=true} + regress_rls_schema | par_col_t1 | table | | {orientation=column,compression=low,enable_rowsecurity=true} + regress_rls_schema | par_row_t1 | table | | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | tt_rep | table | | {orientation=row,compression=no,enable_rowsecurity=true} +(14 rows) + +\df + List of functions + Schema | Name | Result data type | Argument data types | Type | fencedmode | propackage | prokind +--------------------+------------------------+------------------+----------------------------+--------+------------+------------+--------- + regress_rls_schema | rls_auto_create_policy | integer | t_name text, p_num integer | normal | f | f | f + regress_rls_schema | rls_auto_drop_policy | integer | t_name text, p_num integer | normal | f | f | f + regress_rls_schema | rls_fleak1 | boolean | text | normal | f | f | f + regress_rls_schema | rls_fleak2 | boolean | text | normal | f | f | f +(4 rows) + +-- viewpoint from regress_rls_alice again +SET ROLE regress_rls_alice PASSWORD 'Ttest@123'; +ALTER TABLE tt_rep FORCE ROW LEVEL SECURITY; +ALTER TABLE par_row_t1 FORCE ROW LEVEL SECURITY; +\d + List of relations + Schema | Name | Type | Owner | Storage +--------------------+--------------------+-------+-------------------+--------------------------------------------------------------------------------- + regress_rls_schema | account_col | table | regress_rls_alice | {orientation=column,compression=low} + regress_rls_schema | account_row | table | regress_rls_alice | {orientation=row,compression=no} + regress_rls_schema | alice_private | table | regress_rls_alice | {orientation=row,compression=no} + regress_rls_schema | alice_public_1 | table | regress_rls_alice | {orientation=row,compression=no} + regress_rls_schema | alice_public_2 | table | regress_rls_alice | {orientation=row,compression=no} + regress_rls_schema | category_col | table | regress_rls_alice | {orientation=column,compression=low} + regress_rls_schema | category_row | table | regress_rls_alice | {orientation=row,compression=no} + regress_rls_schema | document_col | table | regress_rls_alice | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | document_row | table | regress_rls_alice | {orientation=row,compression=no,enable_rowsecurity=true} + regress_rls_schema | document_row_david | table | | {orientation=row,compression=no} + regress_rls_schema | inlist_t1 | table | | {orientation=row,compression=no,enable_rowsecurity=true,force_rowsecurity=true} + regress_rls_schema | par_col_t1 | table | regress_rls_alice | {orientation=column,compression=low,enable_rowsecurity=true} + regress_rls_schema | par_row_t1 | table | regress_rls_alice | {orientation=row,compression=no,enable_rowsecurity=true,force_rowsecurity=true} + regress_rls_schema | tt_rep | table | regress_rls_alice | {orientation=row,compression=no,enable_rowsecurity=true,force_rowsecurity=true} +(14 rows) + +SELECT * FROM tt_rep ORDER BY id; + id | name +----+------------------- + 1 | regress_rls_alice +(1 row) + +SELECT * FROM par_row_t1 ORDER BY id; + id | a | b +----+----+-------- + 1 | 1 | huawei + 2 | 2 | huawei + 3 | 3 | huawei + 4 | 4 | huawei + 5 | 5 | huawei + 6 | 6 | huawei + 7 | 7 | huawei + 8 | 8 | huawei + 9 | 9 | huawei + 10 | 10 | huawei + 11 | 11 | huawei + 12 | 12 | huawei + 13 | 13 | huawei + 14 | 14 | huawei + 15 | 15 | huawei + 16 | 16 | huawei + 17 | 17 | huawei + 18 | 18 | huawei + 19 | 19 | huawei + 20 | 20 | huawei +(20 rows) + +-- check infinite recursion for rls +CREATE TABLE aa(a int); +CREATE TABLE bb(a int); +ALTER TABLE aa ENABLE ROW LEVEL SECURITY; +ALTER TABLE bb ENABLE ROW LEVEL SECURITY; +CREATE ROW LEVEL SECURITY POLICY aa_rls ON aa USING(EXISTS (SELECT a FROM bb)); +-- create failed because of infinite recursion in rls policy +CREATE ROW LEVEL SECURITY POLICY bb_rls ON bb USING(EXISTS (SELECT a FROM aa)); +ERROR: Create row level security policy "bb_rls" failed, because it will result in infinite recursion for DML queries +ALTER TABLE aa DISABLE ROW LEVEL SECURITY; +-- create succeed because of aa disable row level security +CREATE ROW LEVEL SECURITY POLICY bb_rls ON bb USING(EXISTS (SELECT a FROM aa)); +ALTER TABLE aa ENABLE ROW LEVEL SECURITY; +ALTER TABLE aa FORCE ROW LEVEL SECURITY; +ALTER TABLE bb FORCE ROW LEVEL SECURITY; +-- select failed because of infinite recursion in rls policy +SELECT * FROM aa; +ERROR: infinite recursion detected, please check the row level security policies for relation "aa" +ALTER ROW LEVEL SECURITY POLICY aa_rls ON aa USING(a > 10); +ALTER ROW LEVEL SECURITY POLICY aa_rls ON aa USING(EXISTS (SELECT a FROM bb LIMIT 1)); +ERROR: Alter row level security policy "aa_rls" failed, because it will result in infinite recursion for DML queries +DROP ROW LEVEL SECURITY POLICY aa_rls ON aa; +CREATE ROW LEVEL SECURITY POLICY aa_rls ON aa AS RESTRICTIVE FOR SELECT TO PUBLIC USING(EXISTS(SELECT a FROM (SELECT a + 100 FROM aa WHERE a > 10 and a < 100 GROUP BY a HAVING count(*) >1))); +ERROR: Create row level security policy "aa_rls" failed, because it will result in infinite recursion for DML queries +DROP TABLE aa CASCADE; +NOTICE: drop cascades to row level security policy bb_rls on table bb +DROP TABLE bb CASCADE; +-- check any sublink +create table aa(aa_1 int, aa_2 int, rls int); +create policy aa_rls on aa using (rls = 1); +alter table aa enable row level security; +alter table aa force row level security; +create table bb(bb_1 int, bb_2 int, rls int); +create policy bb_rls on bb using (rls = 1); +alter table bb enable row level security; +alter table bb force row level security; +explain(costs off) select aa_1 from aa, bb where bb_1 = 1 and aa_1 > (select min(aa_1) from aa where aa_2 = bb_2 and aa_2 = 1); + QUERY PLAN +--------------------------------------------------------------------------------- + Nested Loop + Join Filter: (regress_rls_schema.aa.aa_1 > (min(regress_rls_schema.aa.aa_1))) + -> Nested Loop + Join Filter: (regress_rls_schema.bb.bb_2 = regress_rls_schema.aa.aa_2) + -> Seq Scan on bb + Filter: ((rls = 1) AND (bb_1 = 1)) + -> GroupAggregate + Group By Key: regress_rls_schema.aa.aa_2 + -> Nested Loop Semi Join + -> Seq Scan on aa + Filter: ((aa_2 = 1) AND (rls = 1)) + -> Seq Scan on bb + Filter: ((rls = 1) AND (bb_1 = 1) AND (bb_2 = 1)) + -> Seq Scan on aa + Filter: (rls = 1) + Notice: This query is influenced by row level security feature +(16 rows) + +-- clean environment +RESET ROLE; +DROP ROW LEVEL SECURITY POLICY t12 ON inlist_t1; +ERROR: row level policy "t12" for table "inlist_t1" does not exists +DROP ROW LEVEL SECURITY POLICY IF EXISTS t12 ON inlist_t1; +NOTICE: row level security policy "t12" for relation "inlist_t1" does not exist, skipping +DROP SCHEMA regress_rls_schema CASCADE; +NOTICE: drop cascades to 20 other objects +DETAIL: drop cascades to function rls_fleak1(text) +drop cascades to function rls_fleak2(text) +drop cascades to function rls_auto_create_policy(text,integer) +drop cascades to function rls_auto_drop_policy(text,integer) +drop cascades to table account_row +drop cascades to table account_col +drop cascades to table category_row +drop cascades to table category_col +drop cascades to table document_row +drop cascades to table document_col +drop cascades to table par_row_t1 +drop cascades to table par_col_t1 +drop cascades to table tt_rep +drop cascades to table alice_private +drop cascades to table alice_public_1 +drop cascades to table alice_public_2 +drop cascades to table document_row_david +drop cascades to table inlist_t1 +drop cascades to table aa +drop cascades to table bb +DROP USER IF EXISTS regress_rls_alice; +DROP USER IF EXISTS regress_rls_bob; +NOTICE: role "regress_rls_bob" does not exist, skipping +DROP USER IF EXISTS regress_rls_david; +DROP USER IF EXISTS regress_rls_peter; +DROP USER IF EXISTS regress_rls_admin; +DROP USER IF EXISTS regress_rls_single_user; +DROP ROLE IF EXISTS regress_rls_group1; +DROP ROLE IF EXISTS regress_rls_group2; +-- check again +SELECT COUNT(*) FROM pg_rlspolicies; + count +------- + 0 +(1 row) + +SELECT COUNT(*) FROM pg_depend WHERE classid = 3254 OR refclassid = 3254; + count +------- + 0 +(1 row) + +SELECT COUNT(*) FROM pg_shdepend WHERE classid = 3254 OR refclassid = 3254; + count +------- + 0 +(1 row) + diff --git a/contrib/dolphin/expected/case_sensitive_test/single_node_foreign_key.out b/contrib/dolphin/expected/case_sensitive_test/single_node_foreign_key.out new file mode 100644 index 0000000000000000000000000000000000000000..5d8a67e9da8e338f74a356cbf57d1d3c3703d865 --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/single_node_foreign_key.out @@ -0,0 +1,1411 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- FOREIGN KEY +-- +-- MATCH FULL +-- +-- First test, check and cascade +-- +CREATE TABLE PKTABLE ( ptest1 int PRIMARY KEY, ptest2 text ); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( ftest1 int REFERENCES PKTABLE MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE, ftest2 int ); +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 'Test1'); +INSERT INTO PKTABLE VALUES (2, 'Test2'); +INSERT INTO PKTABLE VALUES (3, 'Test3'); +INSERT INTO PKTABLE VALUES (4, 'Test4'); +INSERT INTO PKTABLE VALUES (5, 'Test5'); +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2); +INSERT INTO FKTABLE VALUES (2, 3); +INSERT INTO FKTABLE VALUES (3, 4); +INSERT INTO FKTABLE VALUES (NULL, 1); +-- Insert a failed row into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_ftest1_fkey" +DETAIL: Key (ftest1)=(100) is not present in table "PKTABLE". +-- Check FKTABLE +SELECT * FROM FKTABLE; + ftest1 | ftest2 +--------+-------- + 1 | 2 + 2 | 3 + 3 | 4 + | 1 +(4 rows) + +-- Delete a row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=1; +-- Check FKTABLE for removal of matched row +SELECT * FROM FKTABLE; + ftest1 | ftest2 +--------+-------- + 2 | 3 + 3 | 4 + | 1 +(3 rows) + +-- Update a row from PK TABLE +UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; +-- Check FKTABLE for update of matched row +SELECT * FROM FKTABLE; + ftest1 | ftest2 +--------+-------- + 3 | 4 + | 1 + 1 | 3 +(3 rows) + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +-- +-- check set NULL and table constraint on multiple columns +-- +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 text, PRIMARY KEY(ptest1, ptest2) ); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, CONSTRAINT constrname FOREIGN KEY(ftest1, ftest2) + REFERENCES PKTABLE MATCH FULL ON DELETE SET NULL ON UPDATE SET NULL); +-- Test comments +COMMENT ON CONSTRAINT constrname_wrong ON FKTABLE IS 'fk constraint comment'; +ERROR: constraint "constrname_wrong" for table "FKTABLE" does not exist +COMMENT ON CONSTRAINT constrname ON FKTABLE IS 'fk constraint comment'; +COMMENT ON CONSTRAINT constrname ON FKTABLE IS NULL; +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 2, 'Test1'); +INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2'); +INSERT INTO PKTABLE VALUES (2, 4, 'Test2'); +INSERT INTO PKTABLE VALUES (3, 6, 'Test3'); +INSERT INTO PKTABLE VALUES (4, 8, 'Test4'); +INSERT INTO PKTABLE VALUES (5, 10, 'Test5'); +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2, 4); +INSERT INTO FKTABLE VALUES (1, 3, 5); +INSERT INTO FKTABLE VALUES (2, 4, 8); +INSERT INTO FKTABLE VALUES (3, 6, 12); +INSERT INTO FKTABLE VALUES (NULL, NULL, 0); +-- Insert failed rows into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2, 4); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname" +DETAIL: Key (ftest1, ftest2)=(100, 2) is not present in table "PKTABLE". +INSERT INTO FKTABLE VALUES (2, 2, 4); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname" +DETAIL: Key (ftest1, ftest2)=(2, 2) is not present in table "PKTABLE". +INSERT INTO FKTABLE VALUES (NULL, 2, 4); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname" +DETAIL: MATCH FULL does not allow mixing of null and nonnull key values. +INSERT INTO FKTABLE VALUES (1, NULL, 4); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname" +DETAIL: MATCH FULL does not allow mixing of null and nonnull key values. +-- Check FKTABLE +SELECT * FROM FKTABLE; + ftest1 | ftest2 | ftest3 +--------+--------+-------- + 1 | 2 | 4 + 1 | 3 | 5 + 2 | 4 | 8 + 3 | 6 | 12 + | | 0 +(5 rows) + +-- Delete a row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=1 and ptest2=2; +-- Check FKTABLE for removal of matched row +SELECT * FROM FKTABLE; + ftest1 | ftest2 | ftest3 +--------+--------+-------- + 1 | 3 | 5 + 2 | 4 | 8 + 3 | 6 | 12 + | | 0 + | | 4 +(5 rows) + +-- Delete another row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=5 and ptest2=10; +-- Check FKTABLE (should be no change) +SELECT * FROM FKTABLE; + ftest1 | ftest2 | ftest3 +--------+--------+-------- + 1 | 3 | 5 + 2 | 4 | 8 + 3 | 6 | 12 + | | 0 + | | 4 +(5 rows) + +-- Update a row from PK TABLE +UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; +-- Check FKTABLE for update of matched row +SELECT * FROM FKTABLE; + ftest1 | ftest2 | ftest3 +--------+--------+-------- + 1 | 3 | 5 + 3 | 6 | 12 + | | 0 + | | 4 + | | 8 +(5 rows) + +-- Try altering the column type where foreign keys are involved +ALTER TABLE PKTABLE ALTER COLUMN ptest1 TYPE bigint; +ALTER TABLE FKTABLE ALTER COLUMN ftest1 TYPE bigint; +SELECT * FROM PKTABLE; + ptest1 | ptest2 | ptest3 +--------+--------+--------- + 1 | 3 | Test1-2 + 3 | 6 | Test3 + 4 | 8 | Test4 + 1 | 4 | Test2 +(4 rows) + +SELECT * FROM FKTABLE; + ftest1 | ftest2 | ftest3 +--------+--------+-------- + 1 | 3 | 5 + 3 | 6 | 12 + | | 0 + | | 4 + | | 8 +(5 rows) + +DROP TABLE PKTABLE CASCADE; +NOTICE: drop cascades to constraint constrname on table "FKTABLE" +DROP TABLE FKTABLE; +-- +-- check set default and table constraint on multiple columns +-- +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 text, PRIMARY KEY(ptest1, ptest2) ); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( ftest1 int DEFAULT -1, ftest2 int DEFAULT -2, ftest3 int, CONSTRAINT constrname2 FOREIGN KEY(ftest1, ftest2) + REFERENCES PKTABLE MATCH FULL ON DELETE SET DEFAULT ON UPDATE SET DEFAULT); +-- Insert a value in PKTABLE for default +INSERT INTO PKTABLE VALUES (-1, -2, 'The Default!'); +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 2, 'Test1'); +INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2'); +INSERT INTO PKTABLE VALUES (2, 4, 'Test2'); +INSERT INTO PKTABLE VALUES (3, 6, 'Test3'); +INSERT INTO PKTABLE VALUES (4, 8, 'Test4'); +INSERT INTO PKTABLE VALUES (5, 10, 'Test5'); +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2, 4); +INSERT INTO FKTABLE VALUES (1, 3, 5); +INSERT INTO FKTABLE VALUES (2, 4, 8); +INSERT INTO FKTABLE VALUES (3, 6, 12); +INSERT INTO FKTABLE VALUES (NULL, NULL, 0); +-- Insert failed rows into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2, 4); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname2" +DETAIL: Key (ftest1, ftest2)=(100, 2) is not present in table "PKTABLE". +INSERT INTO FKTABLE VALUES (2, 2, 4); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname2" +DETAIL: Key (ftest1, ftest2)=(2, 2) is not present in table "PKTABLE". +INSERT INTO FKTABLE VALUES (NULL, 2, 4); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname2" +DETAIL: MATCH FULL does not allow mixing of null and nonnull key values. +INSERT INTO FKTABLE VALUES (1, NULL, 4); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname2" +DETAIL: MATCH FULL does not allow mixing of null and nonnull key values. +-- Check FKTABLE +SELECT * FROM FKTABLE; + ftest1 | ftest2 | ftest3 +--------+--------+-------- + 1 | 2 | 4 + 1 | 3 | 5 + 2 | 4 | 8 + 3 | 6 | 12 + | | 0 +(5 rows) + +-- Delete a row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=1 and ptest2=2; +-- Check FKTABLE to check for removal +SELECT * FROM FKTABLE; + ftest1 | ftest2 | ftest3 +--------+--------+-------- + 1 | 3 | 5 + 2 | 4 | 8 + 3 | 6 | 12 + | | 0 + -1 | -2 | 4 +(5 rows) + +-- Delete another row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=5 and ptest2=10; +-- Check FKTABLE (should be no change) +SELECT * FROM FKTABLE; + ftest1 | ftest2 | ftest3 +--------+--------+-------- + 1 | 3 | 5 + 2 | 4 | 8 + 3 | 6 | 12 + | | 0 + -1 | -2 | 4 +(5 rows) + +-- Update a row from PK TABLE +UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; +-- Check FKTABLE for update of matched row +SELECT * FROM FKTABLE; + ftest1 | ftest2 | ftest3 +--------+--------+-------- + 1 | 3 | 5 + 3 | 6 | 12 + | | 0 + -1 | -2 | 4 + -1 | -2 | 8 +(5 rows) + +-- this should fail for lack of CASCADE +DROP TABLE PKTABLE; +ERROR: cannot drop table "PKTABLE" because other objects depend on it +DETAIL: constraint constrname2 on table "FKTABLE" depends on table "PKTABLE" +HINT: Use DROP ... CASCADE to drop the dependent objects too. +DROP TABLE PKTABLE CASCADE; +NOTICE: drop cascades to constraint constrname2 on table "FKTABLE" +DROP TABLE FKTABLE; +-- +-- First test, check with no on delete or on update +-- +CREATE TABLE PKTABLE ( ptest1 int PRIMARY KEY, ptest2 text ); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( ftest1 int REFERENCES PKTABLE MATCH FULL, ftest2 int ); +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 'Test1'); +INSERT INTO PKTABLE VALUES (2, 'Test2'); +INSERT INTO PKTABLE VALUES (3, 'Test3'); +INSERT INTO PKTABLE VALUES (4, 'Test4'); +INSERT INTO PKTABLE VALUES (5, 'Test5'); +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2); +INSERT INTO FKTABLE VALUES (2, 3); +INSERT INTO FKTABLE VALUES (3, 4); +INSERT INTO FKTABLE VALUES (NULL, 1); +-- Insert a failed row into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_ftest1_fkey" +DETAIL: Key (ftest1)=(100) is not present in table "PKTABLE". +-- Check FKTABLE +SELECT * FROM FKTABLE; + ftest1 | ftest2 +--------+-------- + 1 | 2 + 2 | 3 + 3 | 4 + | 1 +(4 rows) + +-- Check PKTABLE +SELECT * FROM PKTABLE; + ptest1 | ptest2 +--------+-------- + 1 | Test1 + 2 | Test2 + 3 | Test3 + 4 | Test4 + 5 | Test5 +(5 rows) + +-- Delete a row from PK TABLE (should fail) +DELETE FROM PKTABLE WHERE ptest1=1; +ERROR: update or delete on table "PKTABLE" violates foreign key constraint "FKTABLE_ftest1_fkey" on table "FKTABLE" +DETAIL: Key (ptest1)=(1) is still referenced from table "FKTABLE". +-- Delete a row from PK TABLE (should succeed) +DELETE FROM PKTABLE WHERE ptest1=5; +-- Check PKTABLE for deletes +SELECT * FROM PKTABLE; + ptest1 | ptest2 +--------+-------- + 1 | Test1 + 2 | Test2 + 3 | Test3 + 4 | Test4 +(4 rows) + +-- Update a row from PK TABLE (should fail) +UPDATE PKTABLE SET ptest1=0 WHERE ptest1=2; +ERROR: update or delete on table "PKTABLE" violates foreign key constraint "FKTABLE_ftest1_fkey" on table "FKTABLE" +DETAIL: Key (ptest1)=(2) is still referenced from table "FKTABLE". +-- Update a row from PK TABLE (should succeed) +UPDATE PKTABLE SET ptest1=0 WHERE ptest1=4; +-- Check PKTABLE for updates +SELECT * FROM PKTABLE; + ptest1 | ptest2 +--------+-------- + 1 | Test1 + 2 | Test2 + 3 | Test3 + 0 | Test4 +(4 rows) + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +-- MATCH unspecified +-- Base test restricting update/delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE); +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname3" +DETAIL: Key (ftest1, ftest2, ftest3)=(1, 2, 7) is not present in table "PKTABLE". +-- Show FKTABLE +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 1 | 2 | 3 | 1 + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 +(5 rows) + +-- Try to update something that should fail +UPDATE PKTABLE set ptest2=5 where ptest2=2; +ERROR: update or delete on table "PKTABLE" violates foreign key constraint "constrname3" on table "FKTABLE" +DETAIL: Key (ptest1, ptest2, ptest3)=(1, 2, 3) is still referenced from table "FKTABLE". +-- Try to update something that should succeed +UPDATE PKTABLE set ptest1=1 WHERE ptest2=3; +-- Try to delete something that should fail +DELETE FROM PKTABLE where ptest1=1 and ptest2=2 and ptest3=3; +ERROR: update or delete on table "PKTABLE" violates foreign key constraint "constrname3" on table "FKTABLE" +DETAIL: Key (ptest1, ptest2, ptest3)=(1, 2, 3) is still referenced from table "FKTABLE". +-- Try to delete something that should work +DELETE FROM PKTABLE where ptest1=2; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 1 | 2 | 3 | test1 + 1 | 3 | 3 | test2 + 1 | 3 | 4 | test3 +(3 rows) + +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 1 | 2 | 3 | 1 + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 +(5 rows) + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +-- cascade update/delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE + ON DELETE CASCADE ON UPDATE CASCADE); +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname3" +DETAIL: Key (ftest1, ftest2, ftest3)=(1, 2, 7) is not present in table "PKTABLE". +-- Show FKTABLE +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 1 | 2 | 3 | 1 + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 +(5 rows) + +-- Try to update something that will cascade +UPDATE PKTABLE set ptest2=5 where ptest2=2; +-- Try to update something that should not cascade +UPDATE PKTABLE set ptest1=1 WHERE ptest2=3; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 2 | 4 | 5 | test4 + 1 | 5 | 3 | test1 + 1 | 3 | 3 | test2 + 1 | 3 | 4 | test3 +(4 rows) + +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 + 1 | 5 | 3 | 1 +(5 rows) + +-- Try to delete something that should cascade +DELETE FROM PKTABLE where ptest1=1 and ptest2=5 and ptest3=3; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 2 | 4 | 5 | test4 + 1 | 3 | 3 | test2 + 1 | 3 | 4 | test3 +(3 rows) + +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 +(4 rows) + +-- Try to delete something that should not have a cascade +DELETE FROM PKTABLE where ptest1=2; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 1 | 3 | 3 | test2 + 1 | 3 | 4 | test3 +(2 rows) + +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 +(4 rows) + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +-- set null update / set default delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( ftest1 int DEFAULT 0, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE + ON DELETE SET DEFAULT ON UPDATE SET NULL); +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +INSERT INTO FKTABLE VALUES (2, 3, 4, 1); +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname3" +DETAIL: Key (ftest1, ftest2, ftest3)=(1, 2, 7) is not present in table "PKTABLE". +-- Show FKTABLE +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 1 | 2 | 3 | 1 + 2 | 3 | 4 | 1 + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 +(6 rows) + +-- Try to update something that will set null +UPDATE PKTABLE set ptest2=5 where ptest2=2; +-- Try to update something that should not set null +UPDATE PKTABLE set ptest2=2 WHERE ptest2=3 and ptest1=1; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 2 | 3 | 4 | test3 + 2 | 4 | 5 | test4 + 1 | 5 | 3 | test1 + 1 | 2 | 3 | test2 +(4 rows) + +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 2 | 3 | 4 | 1 + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 + 1 | | 3 | 1 +(6 rows) + +-- Try to delete something that should set default +DELETE FROM PKTABLE where ptest1=2 and ptest2=3 and ptest3=4; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 2 | 4 | 5 | test4 + 1 | 5 | 3 | test1 + 1 | 2 | 3 | test2 +(3 rows) + +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 + 1 | | 3 | 1 + 0 | | | 1 +(6 rows) + +-- Try to delete something that should not set default +DELETE FROM PKTABLE where ptest2=5; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 2 | 4 | 5 | test4 + 1 | 2 | 3 | test2 +(2 rows) + +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 + 1 | | 3 | 1 + 0 | | | 1 +(6 rows) + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +-- set default update / set null delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( ftest1 int DEFAULT 0, ftest2 int DEFAULT -1, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE + ON DELETE SET NULL ON UPDATE SET DEFAULT); +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); +INSERT INTO PKTABLE VALUES (2, -1, 5, 'test5'); +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +INSERT INTO FKTABLE VALUES (2, 3, 4, 1); +INSERT INTO FKTABLE VALUES (2, 4, 5, 1); +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname3" +DETAIL: Key (ftest1, ftest2, ftest3)=(1, 2, 7) is not present in table "PKTABLE". +-- Show FKTABLE +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 1 | 2 | 3 | 1 + 2 | 3 | 4 | 1 + 2 | 4 | 5 | 1 + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 +(7 rows) + +-- Try to update something that will fail +UPDATE PKTABLE set ptest2=5 where ptest2=2; +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "constrname3" +DETAIL: Key (ftest1, ftest2, ftest3)=(1, -1, 3) is not present in table "PKTABLE". +-- Try to update something that will set default +UPDATE PKTABLE set ptest1=0, ptest2=5, ptest3=10 where ptest2=2; +UPDATE PKTABLE set ptest2=10 where ptest2=4; +-- Try to update something that should not set default +UPDATE PKTABLE set ptest2=2 WHERE ptest2=3 and ptest1=1; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 2 | 3 | 4 | test3 + 2 | -1 | 5 | test5 + 0 | 5 | 10 | test1 + 2 | 10 | 5 | test4 + 1 | 2 | 3 | test2 +(5 rows) + +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + 2 | 3 | 4 | 1 + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 + 0 | -1 | | 1 + 2 | -1 | 5 | 1 +(7 rows) + +-- Try to delete something that should set null +DELETE FROM PKTABLE where ptest1=2 and ptest2=3 and ptest3=4; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 2 | -1 | 5 | test5 + 0 | 5 | 10 | test1 + 2 | 10 | 5 | test4 + 1 | 2 | 3 | test2 +(4 rows) + +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 + 0 | -1 | | 1 + 2 | -1 | 5 | 1 + | | | 1 +(7 rows) + +-- Try to delete something that should not set null +DELETE FROM PKTABLE where ptest2=5; +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + ptest1 | ptest2 | ptest3 | ptest4 +--------+--------+--------+-------- + 2 | -1 | 5 | test5 + 2 | 10 | 5 | test4 + 1 | 2 | 3 | test2 +(3 rows) + +SELECT * from FKTABLE; + ftest1 | ftest2 | ftest3 | ftest4 +--------+--------+--------+-------- + | 2 | 3 | 2 + 2 | | 3 | 3 + | 2 | 7 | 4 + | 3 | 4 | 5 + 0 | -1 | | 1 + 2 | -1 | 5 | 1 + | | | 1 +(7 rows) + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE_FAIL1 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest2) REFERENCES PKTABLE); +ERROR: column "ftest2" referenced in foreign key constraint does not exist +CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1) REFERENCES PKTABLE(ptest2)); +ERROR: column "ptest2" referenced in foreign key constraint does not exist +DROP TABLE FKTABLE_FAIL1; +ERROR: table "FKTABLE_FAIL1" does not exist +DROP TABLE FKTABLE_FAIL2; +ERROR: table "FKTABLE_FAIL2" does not exist +DROP TABLE PKTABLE; +-- Test for referencing column number smaller than referenced constraint +CREATE TABLE PKTABLE (ptest1 int, ptest2 int, UNIQUE(ptest1, ptest2)); +NOTICE: CREATE TABLE / UNIQUE will create implicit index "PKTABLE_ptest1_ptest2_key" for table "PKTABLE" +CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES PKTABLE(ptest1)); +ERROR: there is no unique constraint matching given keys for referenced table "PKTABLE" +DROP TABLE FKTABLE_FAIL1; +ERROR: table "FKTABLE_FAIL1" does not exist +DROP TABLE PKTABLE; +-- +-- Tests for mismatched types +-- +-- Basic one column, two table setup +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +INSERT INTO PKTABLE VALUES(42); +-- This next should fail, because int=inet does not exist +CREATE TABLE FKTABLE (ftest1 inet REFERENCES PKTABLE); +ERROR: foreign key constraint "FKTABLE_ftest1_fkey" cannot be implemented +DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: inet and integer. +-- This should also fail for the same reason, but here we +-- give the column name +CREATE TABLE FKTABLE (ftest1 inet REFERENCES PKTABLE(ptest1)); +ERROR: foreign key constraint "FKTABLE_ftest1_fkey" cannot be implemented +DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: inet and integer. +-- This should succeed, even though they are different types, +-- because int=int8 exists and is a member of the integer opfamily +CREATE TABLE FKTABLE (ftest1 int8 REFERENCES PKTABLE); +-- Check it actually works +INSERT INTO FKTABLE VALUES(42); -- should succeed +INSERT INTO FKTABLE VALUES(43); -- should fail +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_ftest1_fkey" +DETAIL: Key (ftest1)=(43) is not present in table "PKTABLE". +UPDATE FKTABLE SET ftest1 = ftest1; -- should succeed +UPDATE FKTABLE SET ftest1 = ftest1 + 1; -- should fail +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_ftest1_fkey" +DETAIL: Key (ftest1)=(43) is not present in table "PKTABLE". +DROP TABLE FKTABLE; +-- This should fail, because we'd have to cast numeric to int which is +-- not an implicit coercion (or use numeric=numeric, but that's not part +-- of the integer opfamily) +CREATE TABLE FKTABLE (ftest1 numeric REFERENCES PKTABLE); +DROP TABLE PKTABLE; +ERROR: cannot drop table "PKTABLE" because other objects depend on it +DETAIL: constraint FKTABLE_ftest1_fkey on table "FKTABLE" depends on table "PKTABLE" +HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- On the other hand, this should work because int implicitly promotes to +-- numeric, and we allow promotion on the FK side +CREATE TABLE PKTABLE (ptest1 numeric PRIMARY KEY); +ERROR: relation "PKTABLE" already exists in schema "public" +DETAIL: creating new table with existing name in the same schema +INSERT INTO PKTABLE VALUES(42); +ERROR: duplicate key value violates unique constraint "PKTABLE_pkey" +DETAIL: Key (ptest1)=(42) already exists. +CREATE TABLE FKTABLE (ftest1 int REFERENCES PKTABLE); +ERROR: relation "FKTABLE" already exists in schema "public" +DETAIL: creating new table with existing name in the same schema +-- Check it actually works +INSERT INTO FKTABLE VALUES(42); -- should succeed +INSERT INTO FKTABLE VALUES(43); -- should fail +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_ftest1_fkey" +DETAIL: Key (ftest1)=(43) is not present in table "PKTABLE". +UPDATE FKTABLE SET ftest1 = ftest1; -- should succeed +UPDATE FKTABLE SET ftest1 = ftest1 + 1; -- should fail +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_ftest1_fkey" +DETAIL: Key (ftest1)=(43) is not present in table "PKTABLE". +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +-- Two columns, two tables +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2)); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +-- This should fail, because we just chose really odd types +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE); +ERROR: foreign key constraint "FKTABLE_ftest1_fkey" cannot be implemented +DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: cidr and integer. +-- Again, so should this... +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE(ptest1, ptest2)); +ERROR: foreign key constraint "FKTABLE_ftest1_fkey" cannot be implemented +DETAIL: Key columns "ftest1" and "ptest1" are of incompatible types: cidr and integer. +-- This fails because we mixed up the column ordering +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES PKTABLE); +ERROR: foreign key constraint "FKTABLE_ftest2_fkey" cannot be implemented +DETAIL: Key columns "ftest2" and "ptest1" are of incompatible types: inet and integer. +-- As does this... +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES PKTABLE(ptest1, ptest2)); +ERROR: foreign key constraint "FKTABLE_ftest2_fkey" cannot be implemented +DETAIL: Key columns "ftest2" and "ptest1" are of incompatible types: inet and integer. +-- And again.. +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE(ptest2, ptest1)); +ERROR: foreign key constraint "FKTABLE_ftest1_fkey" cannot be implemented +DETAIL: Key columns "ftest1" and "ptest2" are of incompatible types: integer and inet. +-- This works... +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES PKTABLE(ptest2, ptest1)); +DROP TABLE FKTABLE; +-- As does this +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE(ptest1, ptest2)); +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +-- Two columns, same table +-- Make sure this still works... +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES PKTABLE(ptest1, ptest2)); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +DROP TABLE PKTABLE; +-- And this, +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES PKTABLE); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +DROP TABLE PKTABLE; +-- This shouldn't (mixed up columns) +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES PKTABLE(ptest2, ptest1)); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +ERROR: foreign key constraint "PKTABLE_ptest3_fkey" cannot be implemented +DETAIL: Key columns "ptest3" and "ptest2" are of incompatible types: integer and inet. +-- Nor should this... (same reason, we have 4,3 referencing 1,2 which mismatches types +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, +ptest3) REFERENCES PKTABLE(ptest1, ptest2)); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +ERROR: foreign key constraint "PKTABLE_ptest4_fkey" cannot be implemented +DETAIL: Key columns "ptest4" and "ptest1" are of incompatible types: inet and integer. +-- Not this one either... Same as the last one except we didn't defined the columns being referenced. +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, +ptest3) REFERENCES PKTABLE); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +ERROR: foreign key constraint "PKTABLE_ptest4_fkey" cannot be implemented +DETAIL: Key columns "ptest4" and "ptest1" are of incompatible types: inet and integer. +-- +-- Now some cases with Inheritance +-- Basic 2 table case: 1 column of matching types. +create table pktable_base (base1 int not null); +create table PKTABLE (ptest1 int, primary key(base1), unique(base1, ptest1)) Inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +create table FKTABLE (ftest1 int references PKTABLE(base1)); +ERROR: relation "PKTABLE" does not exist +-- now some ins, upd, del +insert into PKTABLE(base1) values (1); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE(base1) values (1); + ^ +insert into PKTABLE(base1) values (2); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE(base1) values (2); + ^ +-- let's insert a non-existent FKTABLE value +insert into FKTABLE(ftest1) values (3); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: insert into FKTABLE(ftest1) values (3); + ^ +-- let's make a valid row for that +insert into PKTABLE(base1) values (3); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE(base1) values (3); + ^ +insert into FKTABLE(ftest1) values (3); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: insert into FKTABLE(ftest1) values (3); + ^ +-- let's try removing a row that should fail from PKTABLE +delete from PKTABLE where base1>2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: delete from PKTABLE where base1>2; + ^ +-- okay, let's try updating all of the base1 values to *4 +-- which should fail. +update PKTABLE set base1=base1*4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: update PKTABLE set base1=base1*4; + ^ +-- okay, let's try an update that should work. +update PKTABLE set base1=base1*4 where base1<3; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: update PKTABLE set base1=base1*4 where base1<3; + ^ +-- and a delete that should work +delete from PKTABLE where base1>3; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: delete from PKTABLE where base1>3; + ^ +-- cleanup +drop table FKTABLE; +ERROR: table "FKTABLE" does not exist +delete from PKTABLE; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: delete from PKTABLE; + ^ +-- Now 2 columns 2 tables, matching types +create table FKTABLE (ftest1 int, ftest2 int, foreign key(ftest1, ftest2) references PKTABLE(base1, ptest1)); +ERROR: relation "PKTABLE" does not exist +-- now some ins, upd, del +insert into PKTABLE(base1, ptest1) values (1, 1); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE(base1, ptest1) values (1, 1); + ^ +insert into PKTABLE(base1, ptest1) values (2, 2); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE(base1, ptest1) values (2, 2); + ^ +-- let's insert a non-existent FKTABLE value +insert into FKTABLE(ftest1, ftest2) values (3, 1); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: insert into FKTABLE(ftest1, ftest2) values (3, 1); + ^ +-- let's make a valid row for that +insert into PKTABLE(base1,ptest1) values (3, 1); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE(base1,ptest1) values (3, 1); + ^ +insert into FKTABLE(ftest1, ftest2) values (3, 1); +ERROR: relation "FKTABLE" does not exist on datanode1 +LINE 1: insert into FKTABLE(ftest1, ftest2) values (3, 1); + ^ +-- let's try removing a row that should fail from PKTABLE +delete from PKTABLE where base1>2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: delete from PKTABLE where base1>2; + ^ +-- okay, let's try updating all of the base1 values to *4 +-- which should fail. +update PKTABLE set base1=base1*4; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: update PKTABLE set base1=base1*4; + ^ +-- okay, let's try an update that should work. +update PKTABLE set base1=base1*4 where base1<3; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: update PKTABLE set base1=base1*4 where base1<3; + ^ +-- and a delete that should work +delete from PKTABLE where base1>3; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: delete from PKTABLE where base1>3; + ^ +-- cleanup +drop table FKTABLE; +ERROR: table "FKTABLE" does not exist +drop table PKTABLE; +ERROR: table "PKTABLE" does not exist +drop table pktable_base; +-- Now we'll do one all in 1 table with 2 columns of matching types +create table pktable_base(base1 int not null, base2 int); +create table PKTABLE(ptest1 int, ptest2 int, primary key(base1, ptest1), foreign key(base2, ptest2) references + PKTABLE(base1, ptest1)) Inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +insert into PKTABLE (base1, ptest1, base2, ptest2) values (1, 1, 1, 1); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE (base1, ptest1, base2, ptest2) values (1... + ^ +insert into PKTABLE (base1, ptest1, base2, ptest2) values (2, 1, 1, 1); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE (base1, ptest1, base2, ptest2) values (2... + ^ +insert into PKTABLE (base1, ptest1, base2, ptest2) values (2, 2, 2, 1); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE (base1, ptest1, base2, ptest2) values (2... + ^ +insert into PKTABLE (base1, ptest1, base2, ptest2) values (1, 3, 2, 2); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE (base1, ptest1, base2, ptest2) values (1... + ^ +-- fails (3,2) isn't in base1, ptest1 +insert into PKTABLE (base1, ptest1, base2, ptest2) values (2, 3, 3, 2); +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: insert into PKTABLE (base1, ptest1, base2, ptest2) values (2... + ^ +-- fails (2,2) is being referenced +delete from PKTABLE where base1=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: delete from PKTABLE where base1=2; + ^ +-- fails (1,1) is being referenced (twice) +update PKTABLE set base1=3 where base1=1; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: update PKTABLE set base1=3 where base1=1; + ^ +-- this sequence of two deletes will work, since after the first there will be no (2,*) references +delete from PKTABLE where base2=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: delete from PKTABLE where base2=2; + ^ +delete from PKTABLE where base1=2; +ERROR: relation "PKTABLE" does not exist on datanode1 +LINE 1: delete from PKTABLE where base1=2; + ^ +drop table PKTABLE; +ERROR: table "PKTABLE" does not exist +drop table pktable_base; +-- 2 columns (2 tables), mismatched types +create table pktable_base(base1 int not null); +create table PKTABLE(ptest1 inet, primary key(base1, ptest1)) Inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +-- just generally bad types (with and without column references on the referenced table) +create table FKTABLE(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references PKTABLE); +ERROR: relation "PKTABLE" does not exist +create table FKTABLE(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references PKTABLE(base1, ptest1)); +ERROR: relation "PKTABLE" does not exist +-- let's mix up which columns reference which +create table FKTABLE(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references PKTABLE); +ERROR: relation "PKTABLE" does not exist +create table FKTABLE(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references PKTABLE(base1, ptest1)); +ERROR: relation "PKTABLE" does not exist +create table FKTABLE(ftest1 int, ftest2 inet, foreign key(ftest1, ftest2) references PKTABLE(ptest1, base1)); +ERROR: relation "PKTABLE" does not exist +drop table PKTABLE; +ERROR: table "PKTABLE" does not exist +drop table pktable_base; +-- 2 columns (1 table), mismatched types +create table pktable_base(base1 int not null, base2 int); +create table PKTABLE(ptest1 inet, ptest2 inet[], primary key(base1, ptest1), foreign key(base2, ptest2) references + PKTABLE(base1, ptest1)) Inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +create table PKTABLE(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(base2, ptest2) references + PKTABLE(ptest1, base1)) Inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +create table PKTABLE(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references + PKTABLE(base1, ptest1)) Inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +create table PKTABLE(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references + PKTABLE(base1, ptest1)) Inherits (pktable_base); +ERROR: CREATE TABLE ... INHERITS is not yet supported. +drop table PKTABLE; +ERROR: table "PKTABLE" does not exist +drop table pktable_base; +-- +-- Deferrable constraints +-- (right now, only FOREIGN KEY constraints can be deferred) +-- +-- deferrable, explicitly deferred +CREATE TABLE PKTABLE ( + id INT4 PRIMARY KEY, + other INT4 +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES PKTABLE DEFERRABLE +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "FKTABLE_pkey" for table "FKTABLE" +-- default to immediate: should fail +INSERT INTO FKTABLE VALUES (5, 10); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_fk_fkey" +DETAIL: Key (fk)=(10) is not present in table "PKTABLE". +-- explicitly defer the constraint +BEGIN; +SET CONSTRAINTS ALL DEFERRED; +INSERT INTO FKTABLE VALUES (10, 15); +INSERT INTO PKTABLE VALUES (15, 0); -- make the FK insert valid +COMMIT; +DROP TABLE FKTABLE, PKTABLE; +-- deferrable, initially deferred +CREATE TABLE PKTABLE ( + id INT4 PRIMARY KEY, + other INT4 +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES PKTABLE DEFERRABLE INITIALLY DEFERRED +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "FKTABLE_pkey" for table "FKTABLE" +-- default to deferred, should succeed +BEGIN; +INSERT INTO FKTABLE VALUES (100, 200); +INSERT INTO PKTABLE VALUES (200, 500); -- make the FK insert valid +COMMIT; +-- default to deferred, explicitly make immediate +BEGIN; +SET CONSTRAINTS ALL IMMEDIATE; +-- should fail +INSERT INTO FKTABLE VALUES (500, 1000); +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_fk_fkey" +DETAIL: Key (fk)=(1000) is not present in table "PKTABLE". +COMMIT; +DROP TABLE FKTABLE, PKTABLE; +-- tricky behavior: according to SQL99, if a deferred constraint is set +-- to 'immediate' mode, it should be checked for validity *immediately*, +-- not when the current transaction commits (i.e. the mode change applies +-- retroactively) +CREATE TABLE PKTABLE ( + id INT4 PRIMARY KEY, + other INT4 +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES PKTABLE DEFERRABLE +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "FKTABLE_pkey" for table "FKTABLE" +BEGIN; +SET CONSTRAINTS ALL DEFERRED; +-- should succeed, for now +INSERT INTO FKTABLE VALUES (1000, 2000); +-- should cause transaction abort, due to preceding error +SET CONSTRAINTS ALL IMMEDIATE; +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_fk_fkey" +DETAIL: Key (fk)=(2000) is not present in table "PKTABLE". +INSERT INTO PKTABLE VALUES (2000, 3); -- too late +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +COMMIT; +DROP TABLE FKTABLE, PKTABLE; +-- deferrable, initially deferred +CREATE TABLE PKTABLE ( + id INT4 PRIMARY KEY, + other INT4 +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TABLE FKTABLE ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES PKTABLE DEFERRABLE INITIALLY DEFERRED +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "FKTABLE_pkey" for table "FKTABLE" +BEGIN; +-- no error here +INSERT INTO FKTABLE VALUES (100, 200); +-- error here on commit +COMMIT; +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_fk_fkey" +DETAIL: Key (fk)=(200) is not present in table "PKTABLE". +DROP TABLE PKTABLE, FKTABLE; +-- test notice about expensive referential integrity checks, +-- where the index cannot be used because of type incompatibilities. +CREATE TEMP TABLE PKTABLE ( + id1 INT4 PRIMARY KEY, + id2 VARCHAR(4) UNIQUE, + id3 REAL UNIQUE, + UNIQUE(id1, id2, id3) +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +NOTICE: CREATE TABLE / UNIQUE will create implicit index "PKTABLE_id2_key" for table "PKTABLE" +NOTICE: CREATE TABLE / UNIQUE will create implicit index "PKTABLE_id3_key" for table "PKTABLE" +NOTICE: CREATE TABLE / UNIQUE will create implicit index "PKTABLE_id1_id2_id3_key" for table "PKTABLE" +CREATE TEMP TABLE FKTABLE ( + x1 INT4 REFERENCES PKTABLE(id1), + x2 VARCHAR(4) REFERENCES PKTABLE(id2), + x3 REAL REFERENCES PKTABLE(id3), + x4 TEXT, + x5 INT2 +); +-- check individual constraints with alter table. +-- should fail +-- varchar does not promote to real +ALTER TABLE FKTABLE ADD CONSTRAINT fk_2_3 +FOREIGN KEY (x2) REFERENCES PKTABLE(id3); +-- nor to int4 +ALTER TABLE FKTABLE ADD CONSTRAINT fk_2_1 +FOREIGN KEY (x2) REFERENCES PKTABLE(id1); +-- real does not promote to int4 +ALTER TABLE FKTABLE ADD CONSTRAINT fk_3_1 +FOREIGN KEY (x3) REFERENCES PKTABLE(id1); +-- int4 does not promote to text +ALTER TABLE FKTABLE ADD CONSTRAINT fk_1_2 +FOREIGN KEY (x1) REFERENCES PKTABLE(id2); +-- should succeed +-- int4 promotes to real +ALTER TABLE FKTABLE ADD CONSTRAINT fk_1_3 +FOREIGN KEY (x1) REFERENCES PKTABLE(id3); +-- text is compatible with varchar +ALTER TABLE FKTABLE ADD CONSTRAINT fk_4_2 +FOREIGN KEY (x4) REFERENCES PKTABLE(id2); +-- int2 is part of integer opfamily as of 8.0 +ALTER TABLE FKTABLE ADD CONSTRAINT fk_5_1 +FOREIGN KEY (x5) REFERENCES PKTABLE(id1); +-- check multikey cases, especially out-of-order column lists +-- these should work +ALTER TABLE FKTABLE ADD CONSTRAINT fk_123_123 +FOREIGN KEY (x1,x2,x3) REFERENCES PKTABLE(id1,id2,id3); +ALTER TABLE FKTABLE ADD CONSTRAINT fk_213_213 +FOREIGN KEY (x2,x1,x3) REFERENCES PKTABLE(id2,id1,id3); +ALTER TABLE FKTABLE ADD CONSTRAINT fk_253_213 +FOREIGN KEY (x2,x5,x3) REFERENCES PKTABLE(id2,id1,id3); +-- these should fail +ALTER TABLE FKTABLE ADD CONSTRAINT fk_123_231 +FOREIGN KEY (x1,x2,x3) REFERENCES PKTABLE(id2,id3,id1); +ALTER TABLE FKTABLE ADD CONSTRAINT fk_241_132 +FOREIGN KEY (x2,x4,x1) REFERENCES PKTABLE(id1,id3,id2); +DROP TABLE PKTABLE, FKTABLE; +-- test a tricky case: we can elide firing the FK check trigger during +-- an UPDATE if the UPDATE did not change the foreign key +-- field. However, we can't do this if our transaction was the one that +-- created the updated row and the trigger is deferred, since our UPDATE +-- will have invalidated the original newly-inserted tuple, and therefore +-- cause the on-INSERT RI trigger not to be fired. +CREATE TEMP TABLE PKTABLE ( + id int primary key, + other int +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "PKTABLE_pkey" for table "PKTABLE" +CREATE TEMP TABLE FKTABLE ( + id int primary key, + fk int references PKTABLE deferrable initially deferred +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "FKTABLE_pkey" for table "FKTABLE" +INSERT INTO PKTABLE VALUES (5, 10); +BEGIN; +-- doesn't match PK, but no error yet +INSERT INTO FKTABLE VALUES (0, 20); +-- don't change FK +UPDATE FKTABLE SET id = id + 1; +-- should catch error from initial INSERT +COMMIT; +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_fk_fkey" +DETAIL: Key (fk)=(20) is not present in table "PKTABLE". +-- check same case when insert is in a different subtransaction than update +BEGIN; +-- doesn't match PK, but no error yet +INSERT INTO FKTABLE VALUES (0, 20); +-- UPDATE will be in a subxact +SAVEPOINT savept1; +-- don't change FK +UPDATE FKTABLE SET id = id + 1; +-- should catch error from initial INSERT +COMMIT; +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_fk_fkey" +DETAIL: Key (fk)=(20) is not present in table "PKTABLE". +BEGIN; +-- INSERT will be in a subxact +SAVEPOINT savept1; +-- doesn't match PK, but no error yet +INSERT INTO FKTABLE VALUES (0, 20); +RELEASE SAVEPOINT savept1; +-- don't change FK +UPDATE FKTABLE SET id = id + 1; +-- should catch error from initial INSERT +COMMIT; +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_fk_fkey" +DETAIL: Key (fk)=(20) is not present in table "PKTABLE". +BEGIN; +-- doesn't match PK, but no error yet +INSERT INTO FKTABLE VALUES (0, 20); +-- UPDATE will be in a subxact +SAVEPOINT savept1; +-- don't change FK +UPDATE FKTABLE SET id = id + 1; +-- Roll back the UPDATE +ROLLBACK TO savept1; +-- should catch error from initial INSERT +COMMIT; +ERROR: insert or update on table "FKTABLE" violates foreign key constraint "FKTABLE_fk_fkey" +DETAIL: Key (fk)=(20) is not present in table "PKTABLE". +-- test order of firing of FK triggers when several RI-induced changes need to +-- be made to the same row. This was broken by subtransaction-related +-- changes in 8.0. +CREATE TEMP TABLE users ( + id INT PRIMARY KEY, + name VARCHAR NOT NULL +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "users_pkey" for table "users" +INSERT INTO users VALUES (1, 'Jozko'); +INSERT INTO users VALUES (2, 'Ferko'); +INSERT INTO users VALUES (3, 'Samko'); +CREATE TEMP TABLE tasks ( + id INT PRIMARY KEY, + owner INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL, + worker INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL, + checked_by INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "tasks_pkey" for table "tasks" +INSERT INTO tasks VALUES (1,1,NULL,NULL); +INSERT INTO tasks VALUES (2,2,2,NULL); +INSERT INTO tasks VALUES (3,3,3,3); +SELECT * FROM tasks; + id | owner | worker | checked_by +----+-------+--------+------------ + 1 | 1 | | + 2 | 2 | 2 | + 3 | 3 | 3 | 3 +(3 rows) + +UPDATE users SET id = 4 WHERE id = 3; +SELECT * FROM tasks; + id | owner | worker | checked_by +----+-------+--------+------------ + 1 | 1 | | + 2 | 2 | 2 | + 3 | 4 | 4 | 4 +(3 rows) + +DELETE FROM users WHERE id = 4; +SELECT * FROM tasks; + id | owner | worker | checked_by +----+-------+--------+------------ + 1 | 1 | | + 2 | 2 | 2 | + 3 | | | +(3 rows) + +-- could fail with only 2 changes to make, if row was already updated +BEGIN; +UPDATE tasks set id=id WHERE id=2; +SELECT * FROM tasks; + id | owner | worker | checked_by +----+-------+--------+------------ + 1 | 1 | | + 3 | | | + 2 | 2 | 2 | +(3 rows) + +DELETE FROM users WHERE id = 2; +SELECT * FROM tasks; + id | owner | worker | checked_by +----+-------+--------+------------ + 1 | 1 | | + 3 | | | + 2 | | | +(3 rows) + +COMMIT; +-- +-- Test self-referential FK with CASCADE (bug #6268) +-- +create temp table selfref ( + a int primary key, + b int, + foreign key (b) references selfref (a) + on update cascade on delete cascade +); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "selfref_pkey" for table "selfref" +insert into selfref (a, b) +values + (0, 0), + (1, 1); +begin; + update selfref set a = 123 where a = 0; + select a, b from selfref; + a | b +-----+----- + 1 | 1 + 123 | 123 +(2 rows) + + update selfref set a = 456 where a = 123; + select a, b from selfref; + a | b +-----+----- + 1 | 1 + 456 | 456 +(2 rows) + +commit; +-- +-- Test deferred FK check on a tuple deleted by a rolled-back subtransaction +-- +create table pktable2(f1 int primary key); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "pktable2_pkey" for table "pktable2" +create table fktable2(f1 int references pktable2 deferrable initially deferred); +insert into pktable2 values(1); +begin; +insert into fktable2 values(1); +savepoint x; +delete from fktable2; +rollback to x; +commit; +begin; +insert into fktable2 values(2); +savepoint x; +delete from fktable2; +rollback to x; +commit; -- fail +ERROR: insert or update on table "fktable2" violates foreign key constraint "fktable2_f1_fkey" +DETAIL: Key (f1)=(2) is not present in table "pktable2". +-- +-- Test that we prevent dropping FK constraint with pending trigger events +-- +begin; +insert into fktable2 values(2); +alter table fktable2 drop constraint fktable2_f1_fkey; +ERROR: cannot ALTER TABLE "fktable2" because it has pending trigger events +commit; +begin; +delete from pktable2 where f1 = 1; +alter table fktable2 drop constraint fktable2_f1_fkey; +ERROR: cannot ALTER TABLE "pktable2" because it has pending trigger events +commit; +drop table pktable2, fktable2; diff --git a/contrib/dolphin/expected/case_sensitive_test/single_node_triggers.out b/contrib/dolphin/expected/case_sensitive_test/single_node_triggers.out new file mode 100644 index 0000000000000000000000000000000000000000..a190c16eb08f9b1c66b7b6d2ce5ab0842caeea4a --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/single_node_triggers.out @@ -0,0 +1,1564 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- TRIGGERS +-- +create table Pkeys (pkey1 int4 not null, pkey2 text not null); +alter table Pkeys add unique(pkey1, pkey2); +NOTICE: ALTER TABLE / ADD UNIQUE will create implicit index "Pkeys_pkey1_pkey2_key" for table "Pkeys" +create table Fkeys (fkey1 int4, fkey2 text, fkey3 int); +create table Fkeys2 (fkey21 int4, fkey22 text, pkey23 int not null); +create index fkeys_i on Fkeys (fkey1, fkey2); +create index fkeys2_i on Fkeys2 (fkey21, fkey22); +create index fkeys2p_i on Fkeys2 (pkey23); +insert into Pkeys values (10, '1'); +insert into Pkeys values (20, '2'); +insert into Pkeys values (30, '3'); +insert into Pkeys values (40, '4'); +insert into Pkeys values (50, '5'); +insert into Pkeys values (60, '6'); +create unique index pkeys_i on Pkeys (pkey1, pkey2); +-- +-- For Fkeys: +-- (fkey1, fkey2) --> Pkeys (pkey1, pkey2) +-- (fkey3) --> Fkeys2 (pkey23) +-- +create trigger check_fkeys_pkey_exist + before insert or update on Fkeys + for each row + execute procedure + check_primary_key ('fkey1', 'fkey2', 'Pkeys', 'pkey1', 'pkey2'); +WARNING: Trigger function with non-plpgsql type is not recommended. +DETAIL: Non-plpgsql trigger function are not shippable by default. +HINT: Unshippable trigger may lead to bad performance. +create trigger check_fkeys_pkey2_exist + before insert or update on Fkeys + for each row + execute procedure check_primary_key ('fkey3', 'Fkeys2', 'pkey23'); +WARNING: Trigger function with non-plpgsql type is not recommended. +DETAIL: Non-plpgsql trigger function are not shippable by default. +HINT: Unshippable trigger may lead to bad performance. +-- +-- For Fkeys2: +-- (fkey21, fkey22) --> Pkeys (pkey1, pkey2) +-- +create trigger check_fkeys2_pkey_exist + before insert or update on Fkeys2 + for each row + execute procedure + check_primary_key ('fkey21', 'fkey22', 'Pkeys', 'pkey1', 'pkey2'); +WARNING: Trigger function with non-plpgsql type is not recommended. +DETAIL: Non-plpgsql trigger function are not shippable by default. +HINT: Unshippable trigger may lead to bad performance. +-- Test comments +COMMENT ON TRIGGER check_fkeys2_pkey_bad ON Fkeys2 IS 'wrong'; +ERROR: trigger "check_fkeys2_pkey_bad" for table "Fkeys2" does not exist +COMMENT ON TRIGGER check_fkeys2_pkey_exist ON Fkeys2 IS 'right'; +COMMENT ON TRIGGER check_fkeys2_pkey_exist ON Fkeys2 IS NULL; +-- +-- For Pkeys: +-- ON DELETE/UPDATE (pkey1, pkey2) CASCADE: +-- Fkeys (fkey1, fkey2) and Fkeys2 (fkey21, fkey22) +-- +create trigger check_pkeys_fkey_cascade + before delete or update on Pkeys + for each row + execute procedure + check_foreign_key (2, 'cascade', 'pkey1', 'pkey2', + 'Fkeys', 'fkey1', 'fkey2', 'Fkeys2', 'fkey21', 'fkey22'); +WARNING: Trigger function with non-plpgsql type is not recommended. +DETAIL: Non-plpgsql trigger function are not shippable by default. +HINT: Unshippable trigger may lead to bad performance. +-- +-- For Fkeys2: +-- ON DELETE/UPDATE (pkey23) RESTRICT: +-- Fkeys (fkey3) +-- +create trigger check_fkeys2_fkey_restrict + before delete or update on Fkeys2 + for each row + execute procedure check_foreign_key (1, 'restrict', 'pkey23', 'Fkeys', 'fkey3'); +WARNING: Trigger function with non-plpgsql type is not recommended. +DETAIL: Non-plpgsql trigger function are not shippable by default. +HINT: Unshippable trigger may lead to bad performance. +insert into Fkeys2 values (10, '1', 1); +ERROR: relation "pkeys" does not exist on datanode1 +LINE 1: select 1 from Pkeys where pkey1 = $1 and pkey2 = $2 + ^ +QUERY: select 1 from Pkeys where pkey1 = $1 and pkey2 = $2 +insert into Fkeys2 values (30, '3', 2); +ERROR: relation "pkeys" does not exist on datanode1 +LINE 1: select 1 from Pkeys where pkey1 = $1 and pkey2 = $2 + ^ +QUERY: select 1 from Pkeys where pkey1 = $1 and pkey2 = $2 +insert into Fkeys2 values (40, '4', 5); +ERROR: relation "pkeys" does not exist on datanode1 +LINE 1: select 1 from Pkeys where pkey1 = $1 and pkey2 = $2 + ^ +QUERY: select 1 from Pkeys where pkey1 = $1 and pkey2 = $2 +insert into Fkeys2 values (50, '5', 3); +ERROR: relation "pkeys" does not exist on datanode1 +LINE 1: select 1 from Pkeys where pkey1 = $1 and pkey2 = $2 + ^ +QUERY: select 1 from Pkeys where pkey1 = $1 and pkey2 = $2 +-- no key in Pkeys +insert into Fkeys2 values (70, '5', 3); +ERROR: relation "pkeys" does not exist on datanode1 +LINE 1: select 1 from Pkeys where pkey1 = $1 and pkey2 = $2 + ^ +QUERY: select 1 from Pkeys where pkey1 = $1 and pkey2 = $2 +insert into Fkeys values (10, '1', 2); +ERROR: relation "fkeys2" does not exist on datanode1 +LINE 1: select 1 from Fkeys2 where pkey23 = $1 + ^ +QUERY: select 1 from Fkeys2 where pkey23 = $1 +insert into Fkeys values (30, '3', 3); +ERROR: relation "fkeys2" does not exist on datanode1 +LINE 1: select 1 from Fkeys2 where pkey23 = $1 + ^ +QUERY: select 1 from Fkeys2 where pkey23 = $1 +insert into Fkeys values (40, '4', 2); +ERROR: relation "fkeys2" does not exist on datanode1 +LINE 1: select 1 from Fkeys2 where pkey23 = $1 + ^ +QUERY: select 1 from Fkeys2 where pkey23 = $1 +insert into Fkeys values (50, '5', 2); +ERROR: relation "fkeys2" does not exist on datanode1 +LINE 1: select 1 from Fkeys2 where pkey23 = $1 + ^ +QUERY: select 1 from Fkeys2 where pkey23 = $1 +-- no key in Pkeys +insert into Fkeys values (70, '5', 1); +ERROR: relation "fkeys2" does not exist on datanode1 +LINE 1: select 1 from Fkeys2 where pkey23 = $1 + ^ +QUERY: select 1 from Fkeys2 where pkey23 = $1 +-- no key in Fkeys2 +insert into Fkeys values (60, '6', 4); +ERROR: relation "fkeys2" does not exist on datanode1 +LINE 1: select 1 from Fkeys2 where pkey23 = $1 + ^ +QUERY: select 1 from Fkeys2 where pkey23 = $1 +delete from Pkeys where pkey1 = 30 and pkey2 = '3'; +ERROR: relation "fkeys" does not exist on datanode1 +LINE 1: delete from Fkeys where fkey1 = $1 and fkey2 = $2 + ^ +QUERY: delete from Fkeys where fkey1 = $1 and fkey2 = $2 +delete from Pkeys where pkey1 = 40 and pkey2 = '4'; +ERROR: relation "fkeys" does not exist on datanode1 +LINE 1: delete from Fkeys where fkey1 = $1 and fkey2 = $2 + ^ +QUERY: delete from Fkeys where fkey1 = $1 and fkey2 = $2 +update Pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 50 and pkey2 = '5'; +ERROR: relation "fkeys" does not exist on datanode1 +LINE 1: update Fkeys set fkey1 = 7 , fkey2 = '70' where fkey1 =... + ^ +QUERY: update Fkeys set fkey1 = 7 , fkey2 = '70' where fkey1 = $1 and fkey2 = $2 +update Pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 10 and pkey2 = '1'; +ERROR: relation "fkeys" does not exist on datanode1 +LINE 1: update Fkeys set fkey1 = 7 , fkey2 = '70' where fkey1 =... + ^ +QUERY: update Fkeys set fkey1 = 7 , fkey2 = '70' where fkey1 = $1 and fkey2 = $2 +DROP TABLE Pkeys; +DROP TABLE Fkeys; +DROP TABLE Fkeys2; +-- -- I've disabled the funny_dup17 test because the new semantics +-- -- of AFTER ROW triggers, which get now fired at the end of a +-- -- query always, cause funny_dup17 to enter an endless loop. +-- -- +-- -- Jan +-- +-- create table dup17 (x int4); +-- +-- create trigger dup17_before +-- before insert on dup17 +-- for each row +-- execute procedure +-- funny_dup17 () +-- ; +-- +-- insert into dup17 values (17); +-- select count(*) from dup17; +-- insert into dup17 values (17); +-- select count(*) from dup17; +-- +-- drop trigger dup17_before on dup17; +-- +-- create trigger dup17_after +-- after insert on dup17 +-- for each row +-- execute procedure +-- funny_dup17 () +-- ; +-- insert into dup17 values (13); +-- select count(*) from dup17 where x = 13; +-- insert into dup17 values (13); +-- select count(*) from dup17 where x = 13; +-- +-- DROP TABLE dup17; +create sequence ttdummy_seq increment 10 start 0 minvalue 0; +create table TTtest ( + price_id int4, + price_val int4, + price_on int4, + price_off int4 default 999999 +); +ALTER TABLE TTtest ADD PRIMARY KEY(price_id, price_val, price_on, price_off); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "TTtest_pkey" for table "TTtest" +create trigger ttdummy + before delete or update on TTtest + for each row + execute procedure + ttdummy (price_on, price_off); +WARNING: Trigger function with non-plpgsql type is not recommended. +DETAIL: Non-plpgsql trigger function are not shippable by default. +HINT: Unshippable trigger may lead to bad performance. +create trigger ttserial + before insert or update on TTtest + for each row + execute procedure + autoinc (price_on, ttdummy_seq); +WARNING: Trigger function with non-plpgsql type is not recommended. +DETAIL: Non-plpgsql trigger function are not shippable by default. +HINT: Unshippable trigger may lead to bad performance. +insert into TTtest values (1, 1, null); +insert into TTtest values (2, 2, null); +insert into TTtest values (3, 3, 0); +select * from TTtest order by 1,2,3,4; + price_id | price_val | price_on | price_off +----------+-----------+----------+----------- + 1 | 1 | 10 | 999999 + 2 | 2 | 20 | 999999 + 3 | 3 | 30 | 999999 +(3 rows) + +delete from TTtest where price_id = 2; +ERROR: relation "tttest" does not exist on datanode1 +LINE 1: INSERT INTO TTtest VALUES ($1, $2, $3, $4) + ^ +QUERY: INSERT INTO TTtest VALUES ($1, $2, $3, $4) +select * from TTtest order by 1,2,3,4; + price_id | price_val | price_on | price_off +----------+-----------+----------+----------- + 1 | 1 | 10 | 999999 + 2 | 2 | 20 | 999999 + 3 | 3 | 30 | 999999 +(3 rows) + +-- what do we see ? +-- get current prices +select * from TTtest where price_off = 999999 order by 1,2,3,4; + price_id | price_val | price_on | price_off +----------+-----------+----------+----------- + 1 | 1 | 10 | 999999 + 2 | 2 | 20 | 999999 + 3 | 3 | 30 | 999999 +(3 rows) + +-- change price for price_id == 3 +update TTtest set price_val = 30 where price_id = 3; +ERROR: relation "tttest" does not exist on datanode1 +LINE 1: INSERT INTO TTtest VALUES ($1, $2, $3, $4) + ^ +QUERY: INSERT INTO TTtest VALUES ($1, $2, $3, $4) +select * from TTtest order by 1,2,3,4; + price_id | price_val | price_on | price_off +----------+-----------+----------+----------- + 1 | 1 | 10 | 999999 + 2 | 2 | 20 | 999999 + 3 | 3 | 30 | 999999 +(3 rows) + +-- now we want to change pric_id in ALL tuples +-- this gets us not what we need +update TTtest set price_id = 5 where price_id = 3; +ERROR: relation "tttest" does not exist on datanode1 +LINE 1: INSERT INTO TTtest VALUES ($1, $2, $3, $4) + ^ +QUERY: INSERT INTO TTtest VALUES ($1, $2, $3, $4) +select * from TTtest order by 1,2,3,4; + price_id | price_val | price_on | price_off +----------+-----------+----------+----------- + 1 | 1 | 10 | 999999 + 2 | 2 | 20 | 999999 + 3 | 3 | 30 | 999999 +(3 rows) + +-- restore data as before last update: +select set_ttdummy(0); + set_ttdummy +------------- + 1 +(1 row) + +delete from TTtest where price_id = 5; +update TTtest set price_off = 999999 where price_val = 30; +select * from TTtest order by 1,2,3,4; + price_id | price_val | price_on | price_off +----------+-----------+----------+----------- + 1 | 1 | 10 | 999999 + 2 | 2 | 20 | 999999 + 3 | 3 | 30 | 999999 +(3 rows) + +-- and try change price_id now! +update TTtest set price_id = 5 where price_id = 3; +ERROR: relation "tttest" does not exist on datanode1 +LINE 1: INSERT INTO TTtest VALUES ($1, $2, $3, $4) + ^ +QUERY: INSERT INTO TTtest VALUES ($1, $2, $3, $4) +select * from TTtest order by 1,2,3,4; + price_id | price_val | price_on | price_off +----------+-----------+----------+----------- + 1 | 1 | 10 | 999999 + 2 | 2 | 20 | 999999 + 3 | 3 | 30 | 999999 +(3 rows) + +-- isn't it what we need ? +select set_ttdummy(1); + set_ttdummy +------------- + 0 +(1 row) + +-- we want to correct some "date" +update TTtest set price_on = -1 where price_id = 1; +ERROR: ttdummy (TTtest): you cannot change price_on and/or price_off columns (use set_ttdummy) +-- but this doesn't work +-- try in this way +select set_ttdummy(0); + set_ttdummy +------------- + 1 +(1 row) + +update TTtest set price_on = -1 where price_id = 1; +ERROR: ttdummy (TTtest): you cannot change price_on and/or price_off columns (use set_ttdummy) +select * from TTtest order by 1,2,3,4; + price_id | price_val | price_on | price_off +----------+-----------+----------+----------- + 1 | 1 | 10 | 999999 + 2 | 2 | 20 | 999999 + 3 | 3 | 30 | 999999 +(3 rows) + +-- isn't it what we need ? +-- get price for price_id == 5 as it was @ "date" 35 +select * from TTtest where price_on <= 35 and price_off > 35 and price_id = 5 order by 1,2,3,4; + price_id | price_val | price_on | price_off +----------+-----------+----------+----------- +(0 rows) + +drop table TTtest; +drop sequence ttdummy_seq; +-- +-- tests for per-statement triggers +-- +CREATE TABLE Log_table (tstamp timestamp default timeofday()::timestamp); +CREATE TABLE Main_table (a int, b int); +ALTER TABLE Main_table ADD PRIMARY KEY(A, B); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "Main_table_pkey" for table "Main_table" +COPY Main_table (a,b) FROM stdin; +CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS ' +BEGIN + RAISE NOTICE ''trigger_func(%) called: action = %, when = %, level = %'', TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL; + RETURN NULL; +END;'; +CREATE TRIGGER before_ins_stmt_trig BEFORE INSERT ON Main_table +FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('before_ins_stmt'); +CREATE TRIGGER after_ins_stmt_trig AFTER INSERT ON Main_table +FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('after_ins_stmt'); +-- +-- if neither 'FOR EACH ROW' nor 'FOR EACH STATEMENT' was specified, +-- CREATE TRIGGER should default to 'FOR EACH STATEMENT' +-- +CREATE TRIGGER after_upd_stmt_trig AFTER UPDATE ON Main_table +EXECUTE PROCEDURE trigger_func('after_upd_stmt'); +CREATE TRIGGER after_upd_row_trig AFTER UPDATE ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_row'); +INSERT INTO Main_table DEFAULT VALUES; +NOTICE: trigger_func(before_ins_stmt) called: action = INSERT, when = BEFORE, level = STATEMENT +ERROR: null value in column "a" violates not-null constraint +DETAIL: Failing row contains (null, null). +UPDATE Main_table SET a = a + 1 WHERE b < 30; +NOTICE: trigger_func(after_upd_row) called: action = UPDATE, when = AFTER, level = ROW +NOTICE: trigger_func(after_upd_row) called: action = UPDATE, when = AFTER, level = ROW +NOTICE: trigger_func(after_upd_row) called: action = UPDATE, when = AFTER, level = ROW +NOTICE: trigger_func(after_upd_row) called: action = UPDATE, when = AFTER, level = ROW +NOTICE: trigger_func(after_upd_stmt) called: action = UPDATE, when = AFTER, level = STATEMENT +-- UPDATE that effects zero rows should still call per-statement trigger +UPDATE Main_table SET a = a + 2 WHERE b > 100; +NOTICE: trigger_func(after_upd_stmt) called: action = UPDATE, when = AFTER, level = STATEMENT +-- COPY should fire per-row and per-statement INSERT triggers +COPY Main_table (a, b) FROM stdin; +NOTICE: trigger_func(before_ins_stmt) called: action = INSERT, when = BEFORE, level = STATEMENT +NOTICE: trigger_func(after_ins_stmt) called: action = INSERT, when = AFTER, level = STATEMENT +SELECT * FROM Main_table ORDER BY a, b; + a | b +----+---- + 6 | 10 + 21 | 20 + 30 | 40 + 31 | 10 + 50 | 35 + 50 | 60 + 81 | 15 +(7 rows) + +-- +-- test triggers with WHEN clause +-- +CREATE TRIGGER modified_a BEFORE UPDATE OF a ON Main_table +FOR EACH ROW WHEN (OLD.a <> NEW.a) EXECUTE PROCEDURE trigger_func('modified_a'); +ERROR: missing FROM-clause entry for table "OLD" +LINE 2: FOR EACH ROW WHEN (OLD.a <> NEW.a) EXECUTE PROCEDURE trigger... + ^ +CREATE TRIGGER modified_any BEFORE UPDATE OF a ON Main_table +FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*) EXECUTE PROCEDURE trigger_func('modified_any'); +ERROR: missing FROM-clause entry for table "OLD" +LINE 2: FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*) EXECUTE PRO... + ^ +CREATE TRIGGER insert_a AFTER INSERT ON Main_table +FOR EACH ROW WHEN (NEW.a = 123) EXECUTE PROCEDURE trigger_func('insert_a'); +ERROR: missing FROM-clause entry for table "NEW" +LINE 2: FOR EACH ROW WHEN (NEW.a = 123) EXECUTE PROCEDURE trigger_fu... + ^ +CREATE TRIGGER delete_a AFTER DELETE ON Main_table +FOR EACH ROW WHEN (OLD.a = 123) EXECUTE PROCEDURE trigger_func('delete_a'); +ERROR: missing FROM-clause entry for table "OLD" +LINE 2: FOR EACH ROW WHEN (OLD.a = 123) EXECUTE PROCEDURE trigger_fu... + ^ +CREATE TRIGGER insert_when BEFORE INSERT ON Main_table +FOR EACH STATEMENT WHEN (true) EXECUTE PROCEDURE trigger_func('insert_when'); +CREATE TRIGGER delete_when AFTER DELETE ON Main_table +FOR EACH STATEMENT WHEN (true) EXECUTE PROCEDURE trigger_func('delete_when'); +INSERT INTO Main_table (a) VALUES (123), (456); +NOTICE: trigger_func(before_ins_stmt) called: action = INSERT, when = BEFORE, level = STATEMENT +NOTICE: trigger_func(insert_when) called: action = INSERT, when = BEFORE, level = STATEMENT +ERROR: null value in column "b" violates not-null constraint +DETAIL: Failing row contains (123, null). +COPY Main_table FROM stdin; +NOTICE: trigger_func(before_ins_stmt) called: action = INSERT, when = BEFORE, level = STATEMENT +NOTICE: trigger_func(insert_when) called: action = INSERT, when = BEFORE, level = STATEMENT +NOTICE: trigger_func(after_ins_stmt) called: action = INSERT, when = AFTER, level = STATEMENT +; +DELETE FROM Main_table WHERE a IN (123, 456); +NOTICE: trigger_func(delete_when) called: action = DELETE, when = AFTER, level = STATEMENT +UPDATE Main_table SET a = 50, b = 60; +ERROR: duplicate key value violates unique constraint "Main_table_pkey" +DETAIL: Key (a, b)=(50, 60) already exists. +SELECT * FROM Main_table ORDER BY a, b; + a | b +----+---- + 6 | 10 + 21 | 20 + 30 | 40 + 31 | 10 + 50 | 35 + 50 | 60 + 81 | 15 +(7 rows) + +SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'Main_table'::regclass AND tgname = 'modified_a'; +ERROR: relation "main_table" does not exist +LINE 1: ...gerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'Main_tabl... + ^ +SELECT pg_get_triggerdef(oid, false) FROM pg_trigger WHERE tgrelid = 'Main_table'::regclass AND tgname = 'modified_a'; +ERROR: relation "main_table" does not exist +LINE 1: ...erdef(oid, false) FROM pg_trigger WHERE tgrelid = 'Main_tabl... + ^ +SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'Main_table'::regclass AND tgname = 'modified_any'; +ERROR: relation "main_table" does not exist +LINE 1: ...gerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'Main_tabl... + ^ +DROP TRIGGER modified_a ON Main_table; +ERROR: relation "main_table" does not exist +DROP TRIGGER modified_any ON Main_table; +ERROR: relation "main_table" does not exist +DROP TRIGGER insert_a ON Main_table; +ERROR: relation "main_table" does not exist +DROP TRIGGER delete_a ON Main_table; +ERROR: relation "main_table" does not exist +DROP TRIGGER insert_when ON Main_table; +ERROR: relation "main_table" does not exist +DROP TRIGGER delete_when ON Main_table; +ERROR: relation "main_table" does not exist +-- Test column-level triggers +DROP TRIGGER after_upd_row_trig ON Main_table; +ERROR: relation "main_table" does not exist +CREATE TRIGGER before_upd_a_row_trig BEFORE UPDATE OF a ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_upd_a_row'); +CREATE TRIGGER after_upd_b_row_trig AFTER UPDATE OF b ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_b_row'); +CREATE TRIGGER after_upd_a_b_row_trig AFTER UPDATE OF a, b ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_a_b_row'); +CREATE TRIGGER before_upd_a_stmt_trig BEFORE UPDATE OF a ON Main_table +FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('before_upd_a_stmt'); +CREATE TRIGGER after_upd_b_stmt_trig AFTER UPDATE OF b ON Main_table +FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('after_upd_b_stmt'); +SELECT pg_get_triggerdef(oid) FROM pg_trigger WHERE tgrelid = 'Main_table'::regclass AND tgname = 'after_upd_a_b_row_trig'; +ERROR: relation "main_table" does not exist +LINE 1: ...t_triggerdef(oid) FROM pg_trigger WHERE tgrelid = 'Main_tabl... + ^ +UPDATE Main_table SET a = 50; +NOTICE: trigger_func(before_upd_a_stmt) called: action = UPDATE, when = BEFORE, level = STATEMENT +NOTICE: trigger_func(before_upd_a_row) called: action = UPDATE, when = BEFORE, level = ROW +NOTICE: trigger_func(before_upd_a_row) called: action = UPDATE, when = BEFORE, level = ROW +NOTICE: trigger_func(before_upd_a_row) called: action = UPDATE, when = BEFORE, level = ROW +NOTICE: trigger_func(before_upd_a_row) called: action = UPDATE, when = BEFORE, level = ROW +NOTICE: trigger_func(before_upd_a_row) called: action = UPDATE, when = BEFORE, level = ROW +NOTICE: trigger_func(before_upd_a_row) called: action = UPDATE, when = BEFORE, level = ROW +NOTICE: trigger_func(before_upd_a_row) called: action = UPDATE, when = BEFORE, level = ROW +NOTICE: trigger_func(after_upd_stmt) called: action = UPDATE, when = AFTER, level = STATEMENT +UPDATE Main_table SET b = 10; +ERROR: duplicate key value violates unique constraint "Main_table_pkey" +DETAIL: Key (a, b)=(50, 10) already exists. +-- +-- Test case for bug with BEFORE trigger followed by AFTER trigger with WHEN +-- +CREATE TABLE some_t (some_col boolean NOT NULL); +ALTER TABLE some_t ADD PRIMARY KEY(some_col); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "some_t_pkey" for table "some_t" +CREATE FUNCTION dummy_update_func() RETURNS trigger AS $$ +BEGIN + RAISE NOTICE 'dummy_update_func(%) called: action = %, old = %, new = %', + TG_ARGV[0], TG_OP, OLD, NEW; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER some_trig_before BEFORE UPDATE ON some_t FOR EACH ROW + EXECUTE PROCEDURE dummy_update_func('before'); +CREATE TRIGGER some_trig_aftera AFTER UPDATE ON some_t FOR EACH ROW + WHEN (NOT OLD.some_col AND NEW.some_col) + EXECUTE PROCEDURE dummy_update_func('aftera'); +ERROR: missing FROM-clause entry for table "OLD" +LINE 2: WHEN (NOT OLD.some_col AND NEW.some_col) + ^ +CREATE TRIGGER some_trig_afterb AFTER UPDATE ON some_t FOR EACH ROW + WHEN (NOT NEW.some_col) + EXECUTE PROCEDURE dummy_update_func('afterb'); +ERROR: missing FROM-clause entry for table "NEW" +LINE 2: WHEN (NOT NEW.some_col) + ^ +INSERT INTO some_t VALUES (TRUE); +UPDATE some_t SET some_col = TRUE; +NOTICE: dummy_update_func(before) called: action = UPDATE, old = (t), new = (t) +UPDATE some_t SET some_col = FALSE; +NOTICE: dummy_update_func(before) called: action = UPDATE, old = (t), new = (f) +UPDATE some_t SET some_col = TRUE; +NOTICE: dummy_update_func(before) called: action = UPDATE, old = (f), new = (t) +DROP TABLE some_t; +-- bogus cases +CREATE TRIGGER error_upd_and_col BEFORE UPDATE OR UPDATE OF a ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('error_upd_and_col'); +ERROR: duplicate trigger events specified at or near "ON" +LINE 1: ...ER error_upd_and_col BEFORE UPDATE OR UPDATE OF a ON Main_ta... + ^ +CREATE TRIGGER error_upd_a_a BEFORE UPDATE OF a, a ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('error_upd_a_a'); +ERROR: column "a" specified more than once +CREATE TRIGGER error_ins_a BEFORE INSERT OF a ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('error_ins_a'); +ERROR: syntax error at or near "OF" +LINE 1: CREATE TRIGGER error_ins_a BEFORE INSERT OF a ON Main_table + ^ +CREATE TRIGGER error_ins_when BEFORE INSERT OR UPDATE ON Main_table +FOR EACH ROW WHEN (OLD.a <> NEW.a) +EXECUTE PROCEDURE trigger_func('error_ins_old'); +ERROR: missing FROM-clause entry for table "OLD" +LINE 2: FOR EACH ROW WHEN (OLD.a <> NEW.a) + ^ +CREATE TRIGGER error_del_when BEFORE DELETE OR UPDATE ON Main_table +FOR EACH ROW WHEN (OLD.a <> NEW.a) +EXECUTE PROCEDURE trigger_func('error_del_new'); +ERROR: missing FROM-clause entry for table "OLD" +LINE 2: FOR EACH ROW WHEN (OLD.a <> NEW.a) + ^ +CREATE TRIGGER error_del_when BEFORE INSERT OR UPDATE ON Main_table +FOR EACH ROW WHEN (NEW.tableoid <> 0) +EXECUTE PROCEDURE trigger_func('error_when_sys_column'); +ERROR: missing FROM-clause entry for table "NEW" +LINE 2: FOR EACH ROW WHEN (NEW.tableoid <> 0) + ^ +CREATE TRIGGER error_stmt_when BEFORE UPDATE OF a ON Main_table +FOR EACH STATEMENT WHEN (OLD.* IS DISTINCT FROM NEW.*) +EXECUTE PROCEDURE trigger_func('error_stmt_when'); +ERROR: missing FROM-clause entry for table "OLD" +LINE 2: FOR EACH STATEMENT WHEN (OLD.* IS DISTINCT FROM NEW.*) + ^ +-- check dependency restrictions +ALTER TABLE Main_table DROP COLUMN b; +ERROR: cannot drop table "Main_table" column b because other objects depend on it +DETAIL: trigger after_upd_b_row_trig on table "Main_table" depends on table "Main_table" column b +trigger after_upd_a_b_row_trig on table "Main_table" depends on table "Main_table" column b +trigger after_upd_b_stmt_trig on table "Main_table" depends on table "Main_table" column b +HINT: Use DROP ... CASCADE to drop the dependent objects too. +-- this should succeed, but we'll roll it back to keep the triggers around +start transaction; +DROP TRIGGER after_upd_a_b_row_trig ON Main_table; +ERROR: relation "main_table" does not exist +DROP TRIGGER after_upd_b_row_trig ON Main_table; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +DROP TRIGGER after_upd_b_stmt_trig ON Main_table; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +ALTER TABLE Main_table DROP COLUMN b; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +rollback; +-- Test enable/disable triggers +create table Trigtest (i serial primary key); +NOTICE: CREATE TABLE will create implicit sequence "Trigtest_i_seq" for serial column "Trigtest.i" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Trigtest_pkey" for table "Trigtest" +-- test that disabling RI triggers works +create table Trigtest2 (i int references Trigtest(i) on delete cascade); +create function Trigtest() returns trigger as $$ +begin + raise notice '% % % %', TG_RELNAME, TG_OP, TG_WHEN, TG_LEVEL; + return new; +end;$$ language plpgsql; +create trigger trigtest_b_row_tg before insert or update or delete on Trigtest +for each row execute procedure Trigtest(); +create trigger trigtest_a_row_tg after insert or update or delete on Trigtest +for each row execute procedure Trigtest(); +create trigger trigtest_b_stmt_tg before insert or update or delete on Trigtest +for each statement execute procedure Trigtest(); +create trigger trigtest_a_stmt_tg after insert or update or delete on Trigtest +for each statement execute procedure Trigtest(); +insert into Trigtest default values; +NOTICE: Trigtest INSERT BEFORE STATEMENT +NOTICE: Trigtest INSERT BEFORE ROW +NOTICE: Trigtest INSERT AFTER ROW +NOTICE: Trigtest INSERT AFTER STATEMENT +alter table Trigtest disable trigger trigtest_b_row_tg; +insert into Trigtest default values; +NOTICE: Trigtest INSERT BEFORE STATEMENT +NOTICE: Trigtest INSERT AFTER ROW +NOTICE: Trigtest INSERT AFTER STATEMENT +alter table Trigtest disable trigger user; +insert into Trigtest default values; +alter table Trigtest enable trigger trigtest_a_stmt_tg; +insert into Trigtest default values; +NOTICE: Trigtest INSERT AFTER STATEMENT +insert into Trigtest2 values(1); +insert into Trigtest2 values(2); +delete from Trigtest where i=2; +NOTICE: Trigtest DELETE AFTER STATEMENT +select * from Trigtest2 order by 1; + i +--- + 1 +(1 row) + +alter table Trigtest disable trigger all; +delete from Trigtest where i=1; +select * from Trigtest2 order by 1; + i +--- + 1 +(1 row) + +-- ensure we still insert, even when all triggers are disabled +insert into Trigtest default values; +select * from Trigtest order by 1; + i +--- + 3 + 4 + 5 +(3 rows) + +drop table Trigtest2; +drop table Trigtest; +-- dump trigger data +CREATE TABLE Trigger_test ( + i int, + v varchar +); +CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger +LANGUAGE plpgsql AS $$ + +declare + + argstr text; + relid text; + +begin + + relid := TG_relid::regclass; + + -- plpgsql can't discover its trigger data in a hash like perl and python + -- can, or by a sort of reflection like tcl can, + -- so we have to hard code the names. + raise NOTICE 'TG_NAME: %', TG_name; + raise NOTICE 'TG_WHEN: %', TG_when; + raise NOTICE 'TG_LEVEL: %', TG_level; + raise NOTICE 'TG_OP: %', TG_op; + raise NOTICE 'TG_RELID::regclass: %', relid; + raise NOTICE 'TG_RELNAME: %', TG_relname; + raise NOTICE 'TG_TABLE_NAME: %', TG_table_name; + raise NOTICE 'TG_TABLE_SCHEMA: %', TG_table_schema; + raise NOTICE 'TG_NARGS: %', TG_nargs; + + argstr := '['; + for i in 0 .. TG_nargs - 1 loop + if i > 0 then + argstr := argstr || ', '; + end if; + argstr := argstr || TG_argv[i]; + end loop; + argstr := argstr || ']'; + raise NOTICE 'TG_ARGV: %', argstr; + + if TG_OP != 'INSERT' then + raise NOTICE 'OLD: %', OLD; + end if; + + if TG_OP != 'DELETE' then + raise NOTICE 'NEW: %', NEW; + end if; + + if TG_OP = 'DELETE' then + return OLD; + else + return NEW; + end if; + +end; +$$; +CREATE TRIGGER show_trigger_data_trig +BEFORE INSERT OR UPDATE OR DELETE ON Trigger_test +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); +insert into Trigger_test values(1,'insert'); +NOTICE: TG_NAME: show_trigger_data_trig +NOTICE: TG_WHEN: BEFORE +NOTICE: TG_LEVEL: ROW +NOTICE: TG_OP: INSERT +NOTICE: TG_RELID::regclass: "Trigger_test" +NOTICE: TG_RELNAME: Trigger_test +NOTICE: TG_TABLE_NAME: Trigger_test +NOTICE: TG_TABLE_SCHEMA: public +NOTICE: TG_NARGS: 2 +NOTICE: TG_ARGV: [23, skidoo] +NOTICE: NEW: (1,insert) +update Trigger_test set v = 'update' where i = 1; +NOTICE: TG_NAME: show_trigger_data_trig +NOTICE: TG_WHEN: BEFORE +NOTICE: TG_LEVEL: ROW +NOTICE: TG_OP: UPDATE +NOTICE: TG_RELID::regclass: "Trigger_test" +NOTICE: TG_RELNAME: Trigger_test +NOTICE: TG_TABLE_NAME: Trigger_test +NOTICE: TG_TABLE_SCHEMA: public +NOTICE: TG_NARGS: 2 +NOTICE: TG_ARGV: [23, skidoo] +NOTICE: OLD: (1,insert) +NOTICE: NEW: (1,update) +delete from Trigger_test; +NOTICE: TG_NAME: show_trigger_data_trig +NOTICE: TG_WHEN: BEFORE +NOTICE: TG_LEVEL: ROW +NOTICE: TG_OP: DELETE +NOTICE: TG_RELID::regclass: "Trigger_test" +NOTICE: TG_RELNAME: Trigger_test +NOTICE: TG_TABLE_NAME: Trigger_test +NOTICE: TG_TABLE_SCHEMA: public +NOTICE: TG_NARGS: 2 +NOTICE: TG_ARGV: [23, skidoo] +NOTICE: OLD: (1,update) +DROP TRIGGER show_trigger_data_trig on Trigger_test; +ERROR: relation "trigger_test" does not exist +DROP FUNCTION trigger_data(); +ERROR: cannot drop function trigger_data() because other objects depend on it +DETAIL: trigger show_trigger_data_trig on table "Trigger_test" depends on function trigger_data() +HINT: Use DROP ... CASCADE to drop the dependent objects too. +DROP TABLE Trigger_test; +-- +-- Test use of row comparisons on OLD/NEW +-- +CREATE TABLE Trigger_test1 (f1 int, f2 text, f3 text); +CREATE TABLE Trigger_test2 (f1 int, f2 text, f3 text); +-- this is the obvious (and wrong...) way to compare rows +CREATE FUNCTION mytrigger() RETURNS trigger LANGUAGE plpgsql as $$ +begin + if row(old.*) = row(new.*) then + raise notice 'row % not changed', new.f1; + else + raise notice 'row % changed', new.f1; + end if; + return new; +end$$; +CREATE TRIGGER t_trigger_test1 +BEFORE UPDATE ON Trigger_test1 +FOR EACH ROW EXECUTE PROCEDURE mytrigger(); +CREATE TRIGGER t_trigger_test2 +BEFORE UPDATE ON Trigger_test2 +FOR EACH ROW EXECUTE PROCEDURE mytrigger(); +INSERT INTO Trigger_test1 VALUES(1, 'foo', 'bar'); +INSERT INTO Trigger_test2 VALUES(2, 'baz', 'quux'); +UPDATE Trigger_test1 SET f3 = 'bar'; +NOTICE: row 1 not changed +UPDATE Trigger_test2 SET f3 = 'bar'; +NOTICE: row 2 changed +UPDATE Trigger_test1 SET f3 = NULL; +NOTICE: row 1 changed +UPDATE Trigger_test2 SET f3 = NULL; +NOTICE: row 2 changed +-- this demonstrates that the above isn't really working as desired: +UPDATE Trigger_test1 SET f3 = NULL; +NOTICE: row 1 changed +UPDATE Trigger_test2 SET f3 = NULL; +NOTICE: row 2 changed +-- the right way when considering nulls is +CREATE OR REPLACE FUNCTION mytrigger() RETURNS trigger LANGUAGE plpgsql as $$ +begin + if row(old.*) is distinct from row(new.*) then + raise notice 'row % changed', new.f1; + else + raise notice 'row % not changed', new.f1; + end if; + return new; +end$$; +UPDATE Trigger_test1 SET f3 = 'bar'; +NOTICE: row 1 changed +UPDATE Trigger_test2 SET f3 = 'bar'; +NOTICE: row 2 changed +UPDATE Trigger_test1 SET f3 = NULL; +NOTICE: row 1 changed +UPDATE Trigger_test2 SET f3 = NULL; +NOTICE: row 2 changed +UPDATE Trigger_test1 SET f3 = NULL; +NOTICE: row 1 not changed +UPDATE Trigger_test2 SET f3 = NULL; +NOTICE: row 2 not changed +DROP TABLE Trigger_test1; +DROP TABLE Trigger_test2; +DROP FUNCTION mytrigger(); +-- Test snapshot management in serializable transactions involving triggers +-- per bug report in 6bc73d4c0910042358k3d1adff3qa36f8df75198ecea@mail.gmail.com +CREATE FUNCTION serializable_update_trig() RETURNS trigger LANGUAGE plpgsql AS +$$ +declare + rec record; +begin + new.description = 'updated in trigger'; + return new; +end; +$$; +CREATE TABLE serializable_update_tab ( + id int, + filler text, + description text +); +ALTER TABLE serializable_update_tab ADD PRIMARY KEY(id); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "serializable_update_tab_pkey" for table "serializable_update_tab" +CREATE TRIGGER serializable_update_trig BEFORE UPDATE ON serializable_update_tab + FOR EACH ROW EXECUTE PROCEDURE serializable_update_trig(); +INSERT INTO serializable_update_tab SELECT a, repeat('xyzxz', 100), 'new' + FROM generate_series(1, 50) a; +START TRANSACTION; +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +UPDATE serializable_update_tab SET description = 'no no', id = 1 WHERE id = 1; +COMMIT; +SELECT description FROM serializable_update_tab WHERE id = 1; + description +-------------------- + updated in trigger +(1 row) + +DROP TABLE serializable_update_tab; +-- minimal update trigger +CREATE TABLE Min_updates_test ( + f1 text, + f2 int, + f3 int); +ALTER TABLE Min_updates_test ADD PRIMARY KEY(F1, F2); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "Min_updates_test_pkey" for table "Min_updates_test" +CREATE TABLE Min_updates_test_oids ( + f1 text, + f2 int, + f3 int) WITH OIDS; +ERROR: CREATE TABLE ... WITH OIDS is not yet supported. +ALTER TABLE Min_updates_test_oids ADD PRIMARY KEY(F1, F2); +ERROR: relation "Min_updates_test_oids" does not exist +INSERT INTO Min_updates_test VALUES ('a',1,2),('b','2',null); +INSERT INTO Min_updates_test_oids VALUES ('a',1,2),('b','2',null); +ERROR: relation "Min_updates_test_oids" does not exist on datanode1 +LINE 1: INSERT INTO Min_updates_test_oids VALUES ('a',1,2),('b','2',... + ^ +CREATE TRIGGER z_min_update +BEFORE UPDATE ON Min_updates_test +FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); +WARNING: Trigger function with non-plpgsql type is not recommended. +DETAIL: Non-plpgsql trigger function are not shippable by default. +HINT: Unshippable trigger may lead to bad performance. +CREATE TRIGGER z_min_update +BEFORE UPDATE ON Min_updates_test_oids +FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); +ERROR: relation "Min_updates_test_oids" does not exist +\set QUIET false +UPDATE Min_updates_test SET f1 = f1; +UPDATE 0 +UPDATE Min_updates_test SET f2 = f2 + 1; +UPDATE 2 +UPDATE Min_updates_test SET f3 = 2 WHERE f3 is null; +UPDATE 1 +UPDATE Min_updates_test_oids SET f1 = f1; +ERROR: relation "Min_updates_test_oids" does not exist on datanode1 +LINE 1: UPDATE Min_updates_test_oids SET f1 = f1; + ^ +UPDATE Min_updates_test_oids SET f2 = f2 + 1; +ERROR: relation "Min_updates_test_oids" does not exist on datanode1 +LINE 1: UPDATE Min_updates_test_oids SET f2 = f2 + 1; + ^ +UPDATE Min_updates_test_oids SET f3 = 2 WHERE f3 is null; +ERROR: relation "Min_updates_test_oids" does not exist on datanode1 +LINE 1: UPDATE Min_updates_test_oids SET f3 = 2 WHERE f3 is null; + ^ +\set QUIET true +SELECT * FROM Min_updates_test ORDER BY 1,2,3; + f1 | f2 | f3 +----+----+---- + a | 2 | 2 + b | 3 | 2 +(2 rows) + +SELECT * FROM Min_updates_test_oids ORDER BY 1,2,3; +ERROR: relation "Min_updates_test_oids" does not exist on datanode1 +LINE 1: SELECT * FROM Min_updates_test_oids ORDER BY 1,2,3; + ^ +DROP TABLE Min_updates_test; +DROP TABLE Min_updates_test_oids; +ERROR: table "Min_updates_test_oids" does not exist +-- +-- Test triggers on views +-- +CREATE VIEW main_view AS SELECT a, b FROM Main_table; +-- Updates should fail without rules or triggers +INSERT INTO main_view VALUES (1,2); +ERROR: cannot insert into view "main_view" +HINT: You need an unconditional ON INSERT DO INSTEAD rule or an INSTEAD OF INSERT trigger. +UPDATE main_view SET b = 20 WHERE a = 50; +ERROR: cannot update view "main_view" +HINT: You need an unconditional ON UPDATE DO INSTEAD rule or an INSTEAD OF UPDATE trigger. +DELETE FROM main_view WHERE a = 50; +ERROR: cannot delete from view "main_view" +HINT: You need an unconditional ON DELETE DO INSTEAD rule or an INSTEAD OF DELETE trigger. +-- Should fail even when there are no matching rows +DELETE FROM main_view WHERE a = 51; +ERROR: cannot delete from view "main_view" +HINT: You need an unconditional ON DELETE DO INSTEAD rule or an INSTEAD OF DELETE trigger. +-- VIEW trigger function +CREATE OR REPLACE FUNCTION view_trigger() RETURNS trigger +LANGUAGE plpgsql AS $$ +declare + argstr text := ''; +begin + for i in 0 .. TG_nargs - 1 loop + if i > 0 then + argstr := argstr || ', '; + end if; + argstr := argstr || TG_argv[i]; + end loop; + + raise notice '% % % % (%)', TG_RELNAME, TG_WHEN, TG_OP, TG_LEVEL, argstr; + + if TG_LEVEL = 'ROW' then + if TG_OP = 'INSERT' then + raise NOTICE 'NEW: %', NEW; + INSERT INTO Main_table VALUES (NEW.a, NEW.b); + RETURN NEW; + end if; + + if TG_OP = 'UPDATE' then + raise NOTICE 'OLD: %, NEW: %', OLD, NEW; + UPDATE Main_table SET a = NEW.a, b = NEW.b WHERE a = OLD.a AND b = OLD.b; + if NOT FOUND then RETURN NULL; end if; + RETURN NEW; + end if; + + if TG_OP = 'DELETE' then + raise NOTICE 'OLD: %', OLD; + DELETE FROM Main_table WHERE a = OLD.a AND b = OLD.b; + if NOT FOUND then RETURN NULL; end if; + RETURN OLD; + end if; + end if; + + RETURN NULL; +end; +$$; +-- Before row triggers aren't allowed on views +CREATE TRIGGER invalid_trig BEFORE INSERT ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_ins_row'); +ERROR: "main_view" is a view +DETAIL: Views cannot have row-level BEFORE or AFTER triggers. +CREATE TRIGGER invalid_trig BEFORE UPDATE ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_upd_row'); +ERROR: "main_view" is a view +DETAIL: Views cannot have row-level BEFORE or AFTER triggers. +CREATE TRIGGER invalid_trig BEFORE DELETE ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_del_row'); +ERROR: "main_view" is a view +DETAIL: Views cannot have row-level BEFORE or AFTER triggers. +-- After row triggers aren't allowed on views +CREATE TRIGGER invalid_trig AFTER INSERT ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_ins_row'); +ERROR: "main_view" is a view +DETAIL: Views cannot have row-level BEFORE or AFTER triggers. +CREATE TRIGGER invalid_trig AFTER UPDATE ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_upd_row'); +ERROR: "main_view" is a view +DETAIL: Views cannot have row-level BEFORE or AFTER triggers. +CREATE TRIGGER invalid_trig AFTER DELETE ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_del_row'); +ERROR: "main_view" is a view +DETAIL: Views cannot have row-level BEFORE or AFTER triggers. +-- Truncate triggers aren't allowed on views +CREATE TRIGGER invalid_trig BEFORE TRUNCATE ON main_view +EXECUTE PROCEDURE trigger_func('before_tru_row'); +ERROR: "main_view" is a view +DETAIL: Views cannot have TRUNCATE triggers. +CREATE TRIGGER invalid_trig AFTER TRUNCATE ON main_view +EXECUTE PROCEDURE trigger_func('before_tru_row'); +ERROR: "main_view" is a view +DETAIL: Views cannot have TRUNCATE triggers. +-- INSTEAD OF triggers aren't allowed on tables +CREATE TRIGGER invalid_trig INSTEAD OF INSERT ON Main_table +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_ins'); +ERROR: "Main_table" is a table +DETAIL: Tables cannot have INSTEAD OF triggers. +CREATE TRIGGER invalid_trig INSTEAD OF UPDATE ON Main_table +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_upd'); +ERROR: "Main_table" is a table +DETAIL: Tables cannot have INSTEAD OF triggers. +CREATE TRIGGER invalid_trig INSTEAD OF DELETE ON Main_table +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_del'); +ERROR: "Main_table" is a table +DETAIL: Tables cannot have INSTEAD OF triggers. +-- Don't support WHEN clauses with INSTEAD OF triggers +CREATE TRIGGER invalid_trig INSTEAD OF UPDATE ON main_view +FOR EACH ROW WHEN (OLD.a <> NEW.a) EXECUTE PROCEDURE view_trigger('instead_of_upd'); +ERROR: INSTEAD OF triggers cannot have WHEN conditions +-- Don't support column-level INSTEAD OF triggers +CREATE TRIGGER invalid_trig INSTEAD OF UPDATE OF a ON main_view +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_upd'); +ERROR: INSTEAD OF triggers cannot have column lists +-- Don't support statement-level INSTEAD OF triggers +CREATE TRIGGER invalid_trig INSTEAD OF UPDATE ON main_view +EXECUTE PROCEDURE view_trigger('instead_of_upd'); +ERROR: INSTEAD OF triggers must be FOR EACH ROW +-- Valid INSTEAD OF triggers +CREATE TRIGGER instead_of_insert_trig INSTEAD OF INSERT ON main_view +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_ins'); +CREATE TRIGGER instead_of_update_trig INSTEAD OF UPDATE ON main_view +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_upd'); +CREATE TRIGGER instead_of_delete_trig INSTEAD OF DELETE ON main_view +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_del'); +-- Valid BEFORE statement VIEW triggers +CREATE TRIGGER before_ins_stmt_trig BEFORE INSERT ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_ins_stmt'); +CREATE TRIGGER before_upd_stmt_trig BEFORE UPDATE ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_upd_stmt'); +CREATE TRIGGER before_del_stmt_trig BEFORE DELETE ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_del_stmt'); +-- Valid AFTER statement VIEW triggers +CREATE TRIGGER after_ins_stmt_trig AFTER INSERT ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_ins_stmt'); +CREATE TRIGGER after_upd_stmt_trig AFTER UPDATE ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_upd_stmt'); +CREATE TRIGGER after_del_stmt_trig AFTER DELETE ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_del_stmt'); +\set QUIET false +-- Insert into view using trigger +INSERT INTO main_view VALUES (20, 30); +NOTICE: main_view BEFORE INSERT STATEMENT (before_view_ins_stmt) +NOTICE: main_view INSTEAD OF INSERT ROW (instead_of_ins) +NOTICE: NEW: (20,30) +ERROR: missing FROM-clause entry for table "NEW" +LINE 1: INSERT INTO Main_table VALUES (NEW.a, NEW.b) + ^ +QUERY: INSERT INTO Main_table VALUES (NEW.a, NEW.b) +CONTEXT: PL/pgSQL function view_trigger() line 17 at SQL statement +INSERT INTO main_view VALUES (21, 31) RETURNING a, b; +NOTICE: main_view BEFORE INSERT STATEMENT (before_view_ins_stmt) +NOTICE: main_view INSTEAD OF INSERT ROW (instead_of_ins) +NOTICE: NEW: (21,31) +ERROR: missing FROM-clause entry for table "NEW" +LINE 1: INSERT INTO Main_table VALUES (NEW.a, NEW.b) + ^ +QUERY: INSERT INTO Main_table VALUES (NEW.a, NEW.b) +CONTEXT: PL/pgSQL function view_trigger() line 17 at SQL statement +-- Table trigger will prevent updates +UPDATE main_view SET b = 31 WHERE a = 20; +NOTICE: main_view BEFORE UPDATE STATEMENT (before_view_upd_stmt) +NOTICE: main_view AFTER UPDATE STATEMENT (after_view_upd_stmt) +UPDATE 0 +UPDATE main_view SET b = 32 WHERE a = 21 AND b = 31 RETURNING a, b; +NOTICE: main_view BEFORE UPDATE STATEMENT (before_view_upd_stmt) +NOTICE: main_view AFTER UPDATE STATEMENT (after_view_upd_stmt) + a | b +---+--- +(0 rows) + +UPDATE 0 +-- Remove table trigger to allow updates +DROP TRIGGER before_upd_a_row_trig ON Main_table; +ERROR: relation "main_table" does not exist +UPDATE main_view SET b = 31 WHERE a = 20; +NOTICE: main_view BEFORE UPDATE STATEMENT (before_view_upd_stmt) +NOTICE: main_view AFTER UPDATE STATEMENT (after_view_upd_stmt) +UPDATE 0 +UPDATE main_view SET b = 32 WHERE a = 21 AND b = 31 RETURNING a, b; +NOTICE: main_view BEFORE UPDATE STATEMENT (before_view_upd_stmt) +NOTICE: main_view AFTER UPDATE STATEMENT (after_view_upd_stmt) + a | b +---+--- +(0 rows) + +UPDATE 0 +-- Before and after stmt triggers should fire even when no rows are affected +UPDATE main_view SET b = 0 WHERE false; +NOTICE: main_view BEFORE UPDATE STATEMENT (before_view_upd_stmt) +NOTICE: main_view AFTER UPDATE STATEMENT (after_view_upd_stmt) +UPDATE 0 +-- Delete from view using trigger +DELETE FROM main_view WHERE a IN (20,21); +NOTICE: main_view BEFORE DELETE STATEMENT (before_view_del_stmt) +NOTICE: main_view INSTEAD OF DELETE ROW (instead_of_del) +NOTICE: OLD: (21,20) +ERROR: missing FROM-clause entry for table "OLD" +LINE 1: DELETE FROM Main_table WHERE a = OLD.a AND b = OLD.b + ^ +QUERY: DELETE FROM Main_table WHERE a = OLD.a AND b = OLD.b +CONTEXT: PL/pgSQL function view_trigger() line 30 at SQL statement +DELETE FROM main_view WHERE a = 31 RETURNING a, b; +NOTICE: main_view BEFORE DELETE STATEMENT (before_view_del_stmt) +NOTICE: main_view INSTEAD OF DELETE ROW (instead_of_del) +NOTICE: OLD: (31,10) +ERROR: missing FROM-clause entry for table "OLD" +LINE 1: DELETE FROM Main_table WHERE a = OLD.a AND b = OLD.b + ^ +QUERY: DELETE FROM Main_table WHERE a = OLD.a AND b = OLD.b +CONTEXT: PL/pgSQL function view_trigger() line 30 at SQL statement +\set QUIET true +-- Describe view should list triggers +\d "main_view" + View "public.main_view" + Column | Type | Modifiers +--------+---------+----------- + a | integer | + b | integer | +Triggers: + after_del_stmt_trig AFTER DELETE ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_del_stmt') + after_ins_stmt_trig AFTER INSERT ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_ins_stmt') + after_upd_stmt_trig AFTER UPDATE ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_upd_stmt') + before_del_stmt_trig BEFORE DELETE ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_del_stmt') + before_ins_stmt_trig BEFORE INSERT ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_ins_stmt') + before_upd_stmt_trig BEFORE UPDATE ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_upd_stmt') + instead_of_delete_trig INSTEAD OF DELETE ON main_view FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_del') + instead_of_insert_trig INSTEAD OF INSERT ON main_view FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_ins') + instead_of_update_trig INSTEAD OF UPDATE ON main_view FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_upd') + +-- Test dropping view triggers +DROP TRIGGER instead_of_insert_trig ON main_view; +DROP TRIGGER instead_of_delete_trig ON main_view; +\d+ "main_view" + View "public.main_view" + Column | Type | Modifiers | Storage | Description +--------+---------+-----------+---------+------------- + a | integer | | plain | + b | integer | | plain | +View definition: + SELECT "Main_table".a, "Main_table".b + FROM "Main_table"; +Triggers: + after_del_stmt_trig AFTER DELETE ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_del_stmt') + after_ins_stmt_trig AFTER INSERT ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_ins_stmt') + after_upd_stmt_trig AFTER UPDATE ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_upd_stmt') + before_del_stmt_trig BEFORE DELETE ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_del_stmt') + before_ins_stmt_trig BEFORE INSERT ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_ins_stmt') + before_upd_stmt_trig BEFORE UPDATE ON main_view FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_upd_stmt') + instead_of_update_trig INSTEAD OF UPDATE ON main_view FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_upd') + +DROP VIEW main_view; +-- +-- Test triggers on a join view +-- +CREATE TABLE country_table ( + country_id serial primary key, + country_name text unique not null, + continent text not null +); +NOTICE: CREATE TABLE will create implicit sequence "country_table_country_id_seq" for serial column "country_table.country_id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "country_table_pkey" for table "country_table" +NOTICE: CREATE TABLE / UNIQUE will create implicit index "country_table_country_name_key" for table "country_table" +INSERT INTO country_table (country_name, continent) + VALUES ('Japan', 'Asia'), + ('UK', 'Europe'), + ('USA', 'North America') + RETURNING *; + country_id | country_name | continent +------------+--------------+--------------- + 1 | Japan | Asia + 2 | UK | Europe + 3 | USA | North America +(3 rows) + +CREATE TABLE city_table ( + city_id serial primary key, + city_name text not null, + population bigint, + country_id int references country_table +); +NOTICE: CREATE TABLE will create implicit sequence "city_table_city_id_seq" for serial column "city_table.city_id" +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "city_table_pkey" for table "city_table" +CREATE VIEW city_view AS + SELECT city_id, city_name, population, country_name, continent + FROM city_table ci + LEFT JOIN country_table co ON co.country_id = ci.country_id; +CREATE FUNCTION city_insert() RETURNS trigger LANGUAGE plpgsql AS $$ +declare + ctry_id int; +begin + if NEW.country_name IS NOT NULL then + SELECT country_id, continent INTO ctry_id, NEW.continent + FROM country_table WHERE country_name = NEW.country_name; + if NOT FOUND then + raise exception 'No such country: "%"', NEW.country_name; + end if; + else + NEW.continent := NULL; + end if; + + if NEW.city_id IS NOT NULL then + INSERT INTO city_table + VALUES(NEW.city_id, NEW.city_name, NEW.population, ctry_id); + else + INSERT INTO city_table(city_name, population, country_id) + VALUES(NEW.city_name, NEW.population, ctry_id) + RETURNING city_id INTO NEW.city_id; + end if; + + RETURN NEW; +end; +$$; +CREATE TRIGGER city_insert_trig INSTEAD OF INSERT ON city_view +FOR EACH ROW EXECUTE PROCEDURE city_insert(); +CREATE FUNCTION city_delete() RETURNS trigger LANGUAGE plpgsql AS $$ +begin + DELETE FROM city_table WHERE city_id = OLD.city_id; + if NOT FOUND then RETURN NULL; end if; + RETURN OLD; +end; +$$; +CREATE TRIGGER city_delete_trig INSTEAD OF DELETE ON city_view +FOR EACH ROW EXECUTE PROCEDURE city_delete(); +CREATE FUNCTION city_update() RETURNS trigger LANGUAGE plpgsql AS $$ +declare + ctry_id int; +begin + if NEW.country_name IS DISTINCT FROM OLD.country_name then + SELECT country_id, continent INTO ctry_id, NEW.continent + FROM country_table WHERE country_name = NEW.country_name; + if NOT FOUND then + raise exception 'No such country: "%"', NEW.country_name; + end if; + + UPDATE city_table SET city_name = NEW.city_name, + population = NEW.population, + country_id = ctry_id + WHERE city_id = OLD.city_id; + else + UPDATE city_table SET city_name = NEW.city_name, + population = NEW.population + WHERE city_id = OLD.city_id; + NEW.continent := OLD.continent; + end if; + + if NOT FOUND then RETURN NULL; end if; + RETURN NEW; +end; +$$; +CREATE TRIGGER city_update_trig INSTEAD OF UPDATE ON city_view +FOR EACH ROW EXECUTE PROCEDURE city_update(); +\set QUIET false +-- INSERT .. RETURNING +INSERT INTO city_view(city_name) VALUES('Tokyo') RETURNING *; +ERROR: missing FROM-clause entry for table "NEW" +LINE 1: SELECT NEW.country_name IS NOT NULL + ^ +QUERY: SELECT NEW.country_name IS NOT NULL +CONTEXT: PL/pgSQL function city_insert() line 5 at IF +INSERT INTO city_view(city_name, population) VALUES('London', 7556900) RETURNING *; +ERROR: missing FROM-clause entry for table "NEW" +LINE 1: SELECT NEW.country_name IS NOT NULL + ^ +QUERY: SELECT NEW.country_name IS NOT NULL +CONTEXT: PL/pgSQL function city_insert() line 5 at IF +INSERT INTO city_view(city_name, country_name) VALUES('Washington DC', 'USA') RETURNING *; +ERROR: missing FROM-clause entry for table "NEW" +LINE 1: SELECT NEW.country_name IS NOT NULL + ^ +QUERY: SELECT NEW.country_name IS NOT NULL +CONTEXT: PL/pgSQL function city_insert() line 5 at IF +INSERT INTO city_view(city_id, city_name) VALUES(123456, 'New York') RETURNING *; +ERROR: missing FROM-clause entry for table "NEW" +LINE 1: SELECT NEW.country_name IS NOT NULL + ^ +QUERY: SELECT NEW.country_name IS NOT NULL +CONTEXT: PL/pgSQL function city_insert() line 5 at IF +INSERT INTO city_view VALUES(234567, 'Birmingham', 1016800, 'UK', 'EU') RETURNING *; +ERROR: missing FROM-clause entry for table "NEW" +LINE 1: SELECT NEW.country_name IS NOT NULL + ^ +QUERY: SELECT NEW.country_name IS NOT NULL +CONTEXT: PL/pgSQL function city_insert() line 5 at IF +-- UPDATE .. RETURNING +UPDATE city_view SET country_name = 'Japon' WHERE city_name = 'Tokyo'; -- error +UPDATE 0 +UPDATE city_view SET country_name = 'Japan' WHERE city_name = 'Takyo'; -- no match +UPDATE 0 +UPDATE city_view SET country_name = 'Japan' WHERE city_name = 'Tokyo' RETURNING *; -- OK + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +UPDATE 0 +UPDATE city_view SET population = 13010279 WHERE city_name = 'Tokyo' RETURNING *; + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +UPDATE 0 +UPDATE city_view SET country_name = 'UK' WHERE city_name = 'New York' RETURNING *; + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +UPDATE 0 +UPDATE city_view SET country_name = 'USA', population = 8391881 WHERE city_name = 'New York' RETURNING *; + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +UPDATE 0 +UPDATE city_view SET continent = 'EU' WHERE continent = 'Europe' RETURNING *; + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +UPDATE 0 +UPDATE city_view v1 SET country_name = v2.country_name FROM city_view v2 + WHERE v2.city_name = 'Birmingham' AND v1.city_name = 'London' RETURNING *; + city_id | city_name | population | country_name | continent | city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+-----------+---------+-----------+------------+--------------+----------- +(0 rows) + +UPDATE 0 +-- DELETE .. RETURNING +DELETE FROM city_view WHERE city_name = 'Birmingham' RETURNING *; + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +DELETE 0 +\set QUIET true +-- read-only view with WHERE clause +CREATE VIEW european_city_view AS + SELECT * FROM city_view WHERE continent = 'Europe'; +SELECT count(*) FROM european_city_view; + count +------- + 0 +(1 row) + +CREATE FUNCTION no_op_trig_fn() RETURNS trigger LANGUAGE plpgsql +AS 'begin RETURN NULL; end'; +CREATE TRIGGER no_op_trig INSTEAD OF INSERT OR UPDATE OR DELETE +ON european_city_view FOR EACH ROW EXECUTE PROCEDURE no_op_trig_fn(); +\set QUIET false +INSERT INTO european_city_view VALUES (0, 'x', 10000, 'y', 'z'); +INSERT 0 0 +UPDATE european_city_view SET population = 10000; +UPDATE 0 +DELETE FROM european_city_view; +DELETE 0 +\set QUIET true +-- rules bypassing no-op triggers +CREATE RULE european_city_insert_rule AS ON INSERT TO european_city_view +DO INSTEAD INSERT INTO city_view +VALUES (NEW.city_id, NEW.city_name, NEW.population, NEW.country_name, NEW.continent) +RETURNING *; +ERROR: missing FROM-clause entry for table "NEW" +LINE 3: VALUES (NEW.city_id, NEW.city_name, NEW.population, NEW.coun... + ^ +CREATE RULE european_city_update_rule AS ON UPDATE TO european_city_view +DO INSTEAD UPDATE city_view SET + city_name = NEW.city_name, + population = NEW.population, + country_name = NEW.country_name +WHERE city_id = OLD.city_id +RETURNING NEW.*; +ERROR: missing FROM-clause entry for table "NEW" +LINE 3: city_name = NEW.city_name, + ^ +CONTEXT: referenced column: city_name +CREATE RULE european_city_delete_rule AS ON DELETE TO european_city_view +DO INSTEAD DELETE FROM city_view WHERE city_id = OLD.city_id RETURNING *; +ERROR: missing FROM-clause entry for table "OLD" +LINE 2: DO INSTEAD DELETE FROM city_view WHERE city_id = OLD.city_id... + ^ +\set QUIET false +-- INSERT not limited by view's WHERE clause, but UPDATE AND DELETE are +INSERT INTO european_city_view(city_name, country_name) + VALUES ('Cambridge', 'USA') RETURNING *; + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +INSERT 0 0 +UPDATE european_city_view SET country_name = 'UK' + WHERE city_name = 'Cambridge'; +UPDATE 0 +DELETE FROM european_city_view WHERE city_name = 'Cambridge'; +DELETE 0 +-- UPDATE and DELETE via rule and trigger +UPDATE city_view SET country_name = 'UK' + WHERE city_name = 'Cambridge' RETURNING *; + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +UPDATE 0 +UPDATE european_city_view SET population = 122800 + WHERE city_name = 'Cambridge' RETURNING *; + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +UPDATE 0 +DELETE FROM european_city_view WHERE city_name = 'Cambridge' RETURNING *; + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +DELETE 0 +-- join UPDATE test +UPDATE city_view v SET population = 599657 + FROM city_table ci, country_table co + WHERE ci.city_name = 'Washington DC' and co.country_name = 'USA' + AND v.city_id = ci.city_id AND v.country_name = co.country_name + RETURNING co.country_id, v.country_name, + v.city_id, v.city_name, v.population; + country_id | country_name | city_id | city_name | population +------------+--------------+---------+-----------+------------ +(0 rows) + +UPDATE 0 +\set QUIET true +SELECT * FROM city_view order by 1; + city_id | city_name | population | country_name | continent +---------+-----------+------------+--------------+----------- +(0 rows) + +DROP TABLE city_table CASCADE; +NOTICE: drop cascades to 2 other objects +DETAIL: drop cascades to view city_view +drop cascades to view european_city_view +DROP TABLE country_table; +-- Test pg_trigger_depth() +create table depth_A (id int not null primary key); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "depth_A_pkey" for table "depth_A" +create table depth_B (id int not null primary key); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "depth_B_pkey" for table "depth_B" +create table depth_C (id int not null primary key); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "depth_C_pkey" for table "depth_C" +create function depth_a_tf() returns trigger + language plpgsql as $$ +begin + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + insert into depth_B values (new.id); + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + return new; +end; +$$; +create trigger depth_a_tr before insert on depth_A + for each row execute procedure depth_a_tf(); +create function depth_b_tf() returns trigger + language plpgsql as $$ +begin + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + begin + execute 'insert into depth_C values (' || new.id::text || ')'; + -- exception + -- when sqlstate 'U9999' then + -- raise notice 'SQLSTATE = U9999: depth = %', pg_trigger_depth(); + end; + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + if new.id = 1 then + execute 'insert into depth_C values (' || new.id::text || ')'; + end if; + return new; +end; +$$; +create trigger depth_b_tr before insert on depth_B + for each row execute procedure depth_b_tf(); +create function depth_c_tf() returns trigger + language plpgsql as $$ +begin + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + if new.id = 1 then + raise exception sqlstate 'U9999'; + end if; + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + return new; +end; +$$; +create trigger depth_c_tr before insert on depth_C + for each row execute procedure depth_c_tf(); +select pg_trigger_depth(); + pg_trigger_depth +------------------ + 0 +(1 row) + +insert into depth_A values (1); +NOTICE: depth_a_tr: depth = 1 +NOTICE: depth_b_tr: depth = 2 +CONTEXT: SQL statement "insert into depth_B values (new.id)" +PL/pgSQL function depth_a_tf() line 4 at SQL statement +ERROR: relation "depth_c" does not exist on datanode1 +LINE 1: insert into depth_C values (1) + ^ +QUERY: insert into depth_C values (1) +CONTEXT: PL/pgSQL function depth_b_tf() line 5 at EXECUTE statement +SQL statement "insert into depth_B values (new.id)" +PL/pgSQL function depth_a_tf() line 4 at SQL statement +select pg_trigger_depth(); + pg_trigger_depth +------------------ + 0 +(1 row) + +insert into depth_A values (2); +NOTICE: depth_a_tr: depth = 1 +NOTICE: depth_b_tr: depth = 2 +CONTEXT: SQL statement "insert into depth_B values (new.id)" +PL/pgSQL function depth_a_tf() line 4 at SQL statement +ERROR: relation "depth_c" does not exist on datanode1 +LINE 1: insert into depth_C values (2) + ^ +QUERY: insert into depth_C values (2) +CONTEXT: PL/pgSQL function depth_b_tf() line 5 at EXECUTE statement +SQL statement "insert into depth_B values (new.id)" +PL/pgSQL function depth_a_tf() line 4 at SQL statement +select pg_trigger_depth(); + pg_trigger_depth +------------------ + 0 +(1 row) + +drop table depth_A, depth_B, depth_C; +drop function depth_a_tf(); +drop function depth_b_tf(); +drop function depth_c_tf(); diff --git a/contrib/dolphin/expected/case_sensitive_test/temp.out b/contrib/dolphin/expected/case_sensitive_test/temp.out new file mode 100644 index 0000000000000000000000000000000000000000..48fddc733b562997a17130c828f888e09660e01b --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/temp.out @@ -0,0 +1,848 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- TEMP +-- Test temp relations and indexes +-- +-- Enforce use of COMMIT instead of 2PC for temporary objects +-- test temp table/index masking +CREATE TABLE temptest(col int); +CREATE INDEX i_temptest ON temptest(col); +CREATE TEMP TABLE temptest(tcol int); +CREATE INDEX i_temptest ON temptest(tcol); +SELECT * FROM temptest; + tcol +------ +(0 rows) + +DROP INDEX i_temptest; +DROP TABLE temptest; +SELECT * FROM temptest; + col +----- +(0 rows) + +DROP INDEX i_temptest; +DROP TABLE temptest; +-- test temp table selects +CREATE TABLE temptest(col int); +INSERT INTO temptest VALUES (1); +CREATE TEMP TABLE temptest(tcol float); +INSERT INTO temptest VALUES (2.1); +SELECT * FROM temptest; + tcol +------ + 2.1 +(1 row) + +DROP TABLE temptest; +SELECT * FROM temptest; + col +----- + 1 +(1 row) + +DROP TABLE temptest; +-- test temp table deletion +CREATE TEMP TABLE temptest(col int); +\c +-- Enforce use of COMMIT instead of 2PC for temporary objects +SELECT * FROM temptest; +ERROR: relation "temptest" does not exist on datanode1 +LINE 1: SELECT * FROM temptest; + ^ +-- Test ON COMMIT DELETE ROWS +CREATE TEMP TABLE temptest(col int) ON COMMIT DELETE ROWS; +START TRANSACTION; +INSERT INTO temptest VALUES (1); +INSERT INTO temptest VALUES (2); +SELECT * FROM temptest ORDER BY 1; + col +----- + 1 + 2 +(2 rows) + +COMMIT; +SELECT * FROM temptest; + col +----- +(0 rows) + +DROP TABLE temptest; +START TRANSACTION; +CREATE TEMP TABLE temptest(col) ON COMMIT PRESERVE ROWS AS SELECT 1; +SELECT * FROM temptest; + col +----- + 1 +(1 row) + +COMMIT; +SELECT * FROM temptest; + col +----- + 1 +(1 row) + +DROP TABLE temptest; +-- Test ON COMMIT DROP +START TRANSACTION; +CREATE TEMP TABLE temptest(col int) ON COMMIT DROP; +ERROR: ON COMMIT only support PRESERVE ROWS or DELETE ROWS option +INSERT INTO temptest VALUES (1); +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +INSERT INTO temptest VALUES (2); +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +SELECT * FROM temptest ORDER BY 1; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +COMMIT; +SELECT * FROM temptest; +ERROR: relation "temptest" does not exist on datanode1 +LINE 1: SELECT * FROM temptest; + ^ +START TRANSACTION; +CREATE TEMP TABLE temptest(col) ON COMMIT DROP AS SELECT 1; +ERROR: ON COMMIT only support PRESERVE ROWS or DELETE ROWS option +SELECT * FROM temptest; +ERROR: current transaction is aborted, commands ignored until end of transaction block, firstChar[Q] +COMMIT; +SELECT * FROM temptest; +ERROR: relation "temptest" does not exist on datanode1 +LINE 1: SELECT * FROM temptest; + ^ +-- Test foreign keys +START TRANSACTION; +CREATE TEMP TABLE temptest1(col int PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "temptest1_pkey" for table "temptest1" +CREATE TEMP TABLE temptest2(col int REFERENCES temptest1) + ON COMMIT DELETE ROWS; +INSERT INTO temptest1 VALUES (1); +INSERT INTO temptest2 VALUES (1); +COMMIT; +SELECT * FROM temptest1; + col +----- + 1 +(1 row) + +SELECT * FROM temptest2; + col +----- +(0 rows) + +START TRANSACTION; +CREATE TEMP TABLE temptest3(col int PRIMARY KEY) ON COMMIT DELETE ROWS; +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "temptest3_pkey" for table "temptest3" +CREATE TEMP TABLE temptest4(col int REFERENCES temptest3); +COMMIT; +ERROR: unsupported ON COMMIT and foreign key combination +DETAIL: Table "temptest4" references "temptest3", but they do not have the same ON COMMIT setting. +-- Test manipulation of temp schema's placement in search path +create table public.whereami (f1 text); +insert into public.whereami values ('public'); +create temp table whereami (f1 text); +insert into whereami values ('temp'); +create function public.whoami() returns text + as $$select 'public'::text$$ language sql; +create function pg_temp.whoami() returns text + as $$select 'temp'::text$$ language sql; +-- default should have pg_temp implicitly first, but only for tables +select * from whereami; + f1 +------ + temp +(1 row) + +select whoami(); + whoami +-------- + public +(1 row) + +-- can list temp first explicitly, but it still doesn't affect functions +set search_path = pg_temp, public; +select * from whereami; + f1 +------ + temp +(1 row) + +select whoami(); + whoami +-------- + public +(1 row) + +-- or put it last for security +set search_path = public, pg_temp; +WARNING: It is invalid to set pg_temp or pg_catalog behind other schemas in search path explicitly. The priority order is pg_temp, pg_catalog and other schemas. +select * from whereami; + f1 +------ + temp +(1 row) + +select whoami(); + whoami +-------- + public +(1 row) + +-- you can invoke a temp function explicitly, though +select pg_temp.whoami(); + whoami +-------- + temp +(1 row) + +drop table public.whereami; +--TEST CASE FOR TEMP TABLE +--1. temp table's feature: +-- 1). Coordinator isolation +-- 2). Session isolation. +-- 3). Auto drop when session quit. +-- 4). Unlogged +-- 5). Other features are the same as ordinary table. +--2. temp table's SQL interface: +-- 1) Create +-- 2) Use +-- 3) Analyze +-- 4) Truncate +-- 5) Discard +-- 6) Alter +--Prepare +create table test_ordinary(a int, b int); +insert into test_ordinary select generate_series(1, 1000), generate_series(1, 1000); +create index ordinary_idx on test_ordinary(a); +create table col_ordinary(a int) with (orientation = column); +insert into col_ordinary select a from test_ordinary; +create sequence test_seq; +create schema test_temp; +create temp table test_base(a int); +insert into test_base select generate_series(1, 1000); +create temp table test_temp1(a int, b varchar2(3000)); +insert into test_temp1 select a, lpad(a, 3000, '-') from test_base; +create index temp1_idx on test_temp1(a, b); +create temp table test_temp2(a int, b varchar2(3000)); +insert into test_temp2 select a, lpad(a, 3000, '+') from test_base; +create index temp2_idx on test_temp2(a); +create temp table temp_col1(a int, b varchar2(3000)) with (orientation = column); +insert into temp_col1 select * from test_temp1; +create index col1_idx on temp_col1(a); +create temp table temp_col2(a int, b varchar2(3000)) with (orientation = column); +insert into temp_col2 select * from temp_col1; +--Session isolation +--Auto drop when session quit. +--Unlogged +--Other features +--temp function +--Create temp table +create local temp table tl(a int, b varchar2(3000)); +create local temporary table lt(a int, b varchar2(3000)); +create temp table pg_temp.temp_t(a int); +ERROR: temporary tables cannot specify a schema name +create table pg_temp.temp_t1(a int); +create temp table temp_t2 as select * from temp_t1; +create temp table pg_temp.temp_t3 as select * from temp_t1; +ERROR: temporary tables cannot specify a schema name +create table pg_temp.temp_t4 as select * from temp_t1; +create temp table pg_temp.temp_t5(like temp_t1); +ERROR: temporary tables cannot specify a schema name +create temp table temp_t6(like temp_t1); +create table pg_temp.temp_t7(like temp_t1); +select * from pg_temp.temp_t1; + a +--- +(0 rows) + +--Analyze +Analyze test_base; +Analyze test_temp1; +select relname, relpages, reltuples from pg_class where relname = 'test_temp1'; + relname | relpages | reltuples +------------+----------+----------- + test_temp1 | 11 | 1000 +(1 row) + +Analyze pg_temp.test_temp2; +select relname, relpages, reltuples from pg_class where relname = 'test_temp2'; + relname | relpages | reltuples +------------+----------+----------- + test_temp2 | 11 | 1000 +(1 row) + +Analyze temp_col1; +select relname, relpages, reltuples from pg_class where relname = 'temp_col1'; + relname | relpages | reltuples +-----------+----------+----------- + temp_col1 | 29 | 1000 +(1 row) + +select relname, relpages, reltuples from pg_class where relname = 'temp_col2'; + relname | relpages | reltuples +-----------+----------+----------- + temp_col2 | 0 | 0 +(1 row) + +Analyze temp_col2; +--Use +select a/0 from test_temp1; +ERROR: division by zero +select * from test_temp1 order by 1 limit 30; + a | b +----+-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + 1 | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------1 + 2 | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------2 + 3 | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------3 + 4 | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------4 + 5 | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------5 + 6 | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------6 + 7 | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------7 + 8 | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------8 + 9 | -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------9 + 10 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------10 + 11 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------11 + 12 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------12 + 13 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------13 + 14 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------14 + 15 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------15 + 16 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------16 + 17 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------17 + 18 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------18 + 19 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------19 + 20 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------20 + 21 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------21 + 22 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------22 + 23 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------23 + 24 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------24 + 25 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------25 + 26 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------26 + 27 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------27 + 28 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------28 + 29 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------29 + 30 | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------30 +(30 rows) + +select t1.a, t2.a from test_temp1 t1, test_temp2 t2 where t1.a = t2.a order by t1.a limit 50; + a | a +----+---- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 10 | 10 + 11 | 11 + 12 | 12 + 13 | 13 + 14 | 14 + 15 | 15 + 16 | 16 + 17 | 17 + 18 | 18 + 19 | 19 + 20 | 20 + 21 | 21 + 22 | 22 + 23 | 23 + 24 | 24 + 25 | 25 + 26 | 26 + 27 | 27 + 28 | 28 + 29 | 29 + 30 | 30 + 31 | 31 + 32 | 32 + 33 | 33 + 34 | 34 + 35 | 35 + 36 | 36 + 37 | 37 + 38 | 38 + 39 | 39 + 40 | 40 + 41 | 41 + 42 | 42 + 43 | 43 + 44 | 44 + 45 | 45 + 46 | 46 + 47 | 47 + 48 | 48 + 49 | 49 + 50 | 50 +(50 rows) + +select t1.a, t2.a from test_temp1 t1, test_ordinary t2 where t1.a = t2.a order by t1.a limit 50; + a | a +----+---- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 10 | 10 + 11 | 11 + 12 | 12 + 13 | 13 + 14 | 14 + 15 | 15 + 16 | 16 + 17 | 17 + 18 | 18 + 19 | 19 + 20 | 20 + 21 | 21 + 22 | 22 + 23 | 23 + 24 | 24 + 25 | 25 + 26 | 26 + 27 | 27 + 28 | 28 + 29 | 29 + 30 | 30 + 31 | 31 + 32 | 32 + 33 | 33 + 34 | 34 + 35 | 35 + 36 | 36 + 37 | 37 + 38 | 38 + 39 | 39 + 40 | 40 + 41 | 41 + 42 | 42 + 43 | 43 + 44 | 44 + 45 | 45 + 46 | 46 + 47 | 47 + 48 | 48 + 49 | 49 + 50 | 50 +(50 rows) + +select t1.a, t2.b from test_temp1 t1, test_ordinary t2 where t1.a = t2.b order by t1.a limit 50; + a | b +----+---- + 1 | 1 + 2 | 2 + 3 | 3 + 4 | 4 + 5 | 5 + 6 | 6 + 7 | 7 + 8 | 8 + 9 | 9 + 10 | 10 + 11 | 11 + 12 | 12 + 13 | 13 + 14 | 14 + 15 | 15 + 16 | 16 + 17 | 17 + 18 | 18 + 19 | 19 + 20 | 20 + 21 | 21 + 22 | 22 + 23 | 23 + 24 | 24 + 25 | 25 + 26 | 26 + 27 | 27 + 28 | 28 + 29 | 29 + 30 | 30 + 31 | 31 + 32 | 32 + 33 | 33 + 34 | 34 + 35 | 35 + 36 | 36 + 37 | 37 + 38 | 38 + 39 | 39 + 40 | 40 + 41 | 41 + 42 | 42 + 43 | 43 + 44 | 44 + 45 | 45 + 46 | 46 + 47 | 47 + 48 | 48 + 49 | 49 + 50 | 50 +(50 rows) + +explain select t1.a, t2.a from test_temp1 t1, test_col t2 where t1.a = t2.a order by t1.a limit 50; +ERROR: relation "test_col" does not exist on datanode1 +LINE 1: explain select t1.a, t2.a from test_temp1 t1, test_col t2 wh... + ^ +select t1.a, t2.a from test_temp1 t1, test_col t2 where t1.a = t2.a order by t1.a limit 50; +ERROR: relation "test_col" does not exist on datanode1 +LINE 1: select t1.a, t2.a from test_temp1 t1, test_col t2 where t1.a... + ^ +--test Alter +Alter table test_temp1 rename to test_temp3; +Alter table test_temp3 set schema pg_temp; +--?ERROR: table test_temp3 is already in schema "pg_temp_.* +Alter table test_temp3 set schema public; +ERROR: cannot move objects into or out of temporary schemas +Alter table test_temp3 rename to test_temp1; +--Col Table +select t1.a from temp_col1 t1, col_ordinary t2 where t1.a = t2.a order by 1 limit 30; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 +(30 rows) + +select t1.a from temp_col1 t1, temp_col2 t2 where t1.a = t2.a order by 1 limit 30; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 +(30 rows) + +select t1.a from test_temp1 t1, temp_col1 t2 where t1.a = t2.a order by 1 limit 30; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 +(30 rows) + +Alter temp_col1 rename to temp_col2; +ERROR: syntax error at or near "temp_col1" +LINE 1: Alter temp_col1 rename to temp_col2; + ^ +Create view col_v1 as select * from temp_col2; +NOTICE: view "col_v1" will be a temporary view +Alter view col_v1 alter a set default 1; +Drop view col_v1; +--test View +create view v1 as select * from test_temp1; +NOTICE: view "v1" will be a temporary view +select a from v1 order by 1 limit 50; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 +(50 rows) + +create view v2 as select t1.a from test_temp1 t1, test_ordinary t2 where t1.a = t2.a; +NOTICE: view "v2" will be a temporary view +select a from v2 order by a limit 50; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 +(50 rows) + +create view v3 as select t1.a from test_temp1 t1, test_temp2 t2 where t1.a = t2.a; +NOTICE: view "v3" will be a temporary view +select a from v3 order by a limit 50; + a +---- + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16 + 17 + 18 + 19 + 20 + 21 + 22 + 23 + 24 + 25 + 26 + 27 + 28 + 29 + 30 + 31 + 32 + 33 + 34 + 35 + 36 + 37 + 38 + 39 + 40 + 41 + 42 + 43 + 44 + 45 + 46 + 47 + 48 + 49 + 50 +(50 rows) + +alter view v2 rename to v4; +alter view v4 alter a set default 1; +alter view v4 set schema test_temp; +ERROR: cannot move objects into or out of temporary schemas +create view v5 as select * from test_ordinary; +drop view v1, v5; +drop view v1; +ERROR: view "v1" does not exist +drop view v3,v4; +--test SEQ +create temp sequence temp_seq; +ERROR: Temporary sequences are not supported +alter sequence temp_seq rename to temp_seq1; +ERROR: relation "temp_seq" does not exist +alter sequence temp_seq1 minvalue 10; +ERROR: relation "temp_seq1" does not exist +drop sequence test_seq; +create temp table test_serial(a serial, b varchar2(100)); +ERROR: It's not supported to create serial column on temporary table +create temp table test_serial2(a int); +alter table test_serial2 add b serial; +ERROR: It's not supported to create serial column on temporary table +drop table test_serial; +ERROR: table "test_serial" does not exist +drop table test_serial2; +--test rule +--test trigger +--test Reindex +reindex index temp1_idx, ordinary_idx; +ERROR: syntax error at or near "," +LINE 1: reindex index temp1_idx, ordinary_idx; + ^ +reindex index temp1_idx; +reindex index temp2_idx; +reindex table test_temp1; +--test Drop index +drop index temp1_idx, ordinary_idx; +drop index temp1_idx, temp2_idx; +ERROR: index "temp1_idx" does not exist +--Vacuum +vacuum test_temp1; +vacuum test_temp2; +vacuum full test_temp1; +vacuum full test_temp2; +--Truncate +Truncate test_base; +Truncate test_temp1; +Truncate test_temp2; +Truncate test_col; +ERROR: relation "test_col" does not exist +--Test Drop +Drop table test_base; +Drop table test_temp1, test_ordinary; +Drop table test_temp1, test_temp2; +ERROR: table "test_temp1" does not exist +Drop table temp_col1, temp_col2; diff --git a/contrib/dolphin/expected/case_sensitive_test/update.out b/contrib/dolphin/expected/case_sensitive_test/update.out new file mode 100644 index 0000000000000000000000000000000000000000..1c87d9ef820c6fa17c0aa24bc7d238d4f592593e --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/update.out @@ -0,0 +1,804 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- UPDATE syntax tests +-- +CREATE TABLE Update_Test ( + a INT DEFAULT 10, + b INT, + c TEXT +); +INSERT INTO Update_Test VALUES (5, 10, 'foo'); +INSERT INTO Update_Test(b, a) VALUES (15, 10); +SELECT * FROM Update_Test ORDER BY a, b, c; + a | b | c +----+----+----- + 5 | 10 | foo + 10 | 15 | +(2 rows) + +UPDATE Update_Test SET a = DEFAULT, b = DEFAULT; +SELECT * FROM Update_Test ORDER BY a, b, c; + a | b | c +----+---+----- + 10 | | foo + 10 | | +(2 rows) + +-- aliases for the UPDATE target table +UPDATE Update_Test AS t SET b = 10 WHERE t.a = 10; +SELECT * FROM Update_Test ORDER BY a, b, c; + a | b | c +----+----+----- + 10 | 10 | foo + 10 | 10 | +(2 rows) + +UPDATE Update_Test t SET b = t.b + 10 WHERE t.a = 10; +SELECT * FROM Update_Test ORDER BY a, b, c; + a | b | c +----+----+----- + 10 | 20 | foo + 10 | 20 | +(2 rows) + +-- +-- Test VALUES in FROM +-- +UPDATE Update_Test SET a=v.i FROM (VALUES(100, 20)) AS v(i, j) + WHERE Update_Test.b = v.j; +SELECT * FROM Update_Test ORDER BY a, b, c; + a | b | c +-----+----+----- + 100 | 20 | foo + 100 | 20 | +(2 rows) + +-- +-- Test multiple-set-clause syntax +-- +UPDATE Update_Test SET (c,b,a) = ('bugle', b+11, DEFAULT) WHERE c = 'foo'; +SELECT * FROM Update_Test ORDER BY a, b, c; + a | b | c +-----+----+------- + 10 | 31 | bugle + 100 | 20 | +(2 rows) + +UPDATE Update_Test SET (c,b) = ('car', a+b), a = a + 1 WHERE a = 10; +SELECT * FROM Update_Test ORDER BY a, b, c; + a | b | c +-----+----+----- + 11 | 41 | car + 100 | 20 | +(2 rows) + +-- fail, multi assignment to same column: +UPDATE Update_Test SET (c,b) = ('car', a+b), b = a + 1 WHERE a = 10; +ERROR: multiple assignments to same column "b" +-- XXX this should work, but doesn't yet: +UPDATE Update_Test SET (a,b) = (select a,b FROM Update_Test where c = 'foo') + WHERE a = 10; +-- if an alias for the target table is specified, don't allow references +-- to the original table name +UPDATE Update_Test AS t SET b = Update_Test.b + 10 WHERE t.a = 10; +ERROR: invalid reference to FROM-clause entry for table "Update_Test" +LINE 1: UPDATE Update_Test AS t SET b = Update_Test.b + 10 WHERE t.a... + ^ +HINT: Perhaps you meant to reference the table alias "t". +CONTEXT: referenced column: b +-- Make sure that we can update to a TOASTed value. +UPDATE Update_Test SET c = repeat('x', 10000) WHERE c = 'car'; +SELECT a, b, char_length(c) FROM Update_Test ORDER BY a; + a | b | char_length +-----+----+------------- + 11 | 41 | 10000 + 100 | 20 | +(2 rows) + +DROP TABLE Update_Test; +--Test "update tablename AS aliasname SET aliasname.colname = colvalue;" +CREATE TABLE Update_Test_c( + a INT DEFAULT 10 +); +CREATE TABLE Update_Test_d( + a INT DEFAULT 10, + b INT +); +INSERT INTO Update_Test_c (a) VALUES (1); +SELECT * FROM Update_Test_c; + a +--- + 1 +(1 row) + +UPDATE Update_Test_c AS test_c SET test_c.a = 2; +SELECT * FROM Update_Test_c; + a +--- + 2 +(1 row) + +UPDATE Update_Test_c AS test_c SET test_c.a = 3 WHERE test_c.a = 2; +SELECT * FROM Update_Test_c; + a +--- + 3 +(1 row) + +UPDATE Update_Test_c test_c SET test_c.a = 4; +SELECT * FROM Update_Test_c; + a +--- + 4 +(1 row) + +UPDATE Update_Test_c AS test_c SET test_c.a = 5 WHERE test_c.a = 4; +SELECT * FROM Update_Test_c; + a +--- + 5 +(1 row) + +UPDATE Update_Test_c AS test_c SET test_a.a = 6; +ERROR: column "test_a.a" of relation "Update_Test_c" does not exist +LINE 1: UPDATE Update_Test_c AS test_c SET test_a.a = 6; + ^ +SELECT * FROM Update_Test_c; + a +--- + 5 +(1 row) + +UPDATE Update_Test_c test_c SET test_a.a = 7; +ERROR: column "test_a.a" of relation "Update_Test_c" does not exist +LINE 1: UPDATE Update_Test_c test_c SET test_a.a = 7; + ^ +SELECT * FROM Update_Test_c; + a +--- + 5 +(1 row) + +INSERT INTO Update_Test_d (a,b) VALUES (1,2); +SELECT * FROM Update_Test_d; + a | b +---+--- + 1 | 2 +(1 row) + +UPDATE Update_Test_d AS test_D SET test_D.a = 3, test_D.b = 4; +SELECT * FROM Update_Test_d; + a | b +---+--- + 3 | 4 +(1 row) + +UPDATE Update_Test_d AS test_D SET test_D.a = 5, test_D.b = 6 WHERE test_D.a = 3 AND test_D.b = 4; +SELECT * FROM Update_Test_d; + a | b +---+--- + 5 | 6 +(1 row) + +UPDATE Update_Test_d test_D SET test_D.a = 7, test_D.b = 8; +SELECT * FROM Update_Test_d; + a | b +---+--- + 7 | 8 +(1 row) + +UPDATE Update_Test_d test_D SET test_D.a = 9, test_D.b = 10 WHERE test_D.a = 7 AND test_D.b = 8; +SELECT * FROM Update_Test_d; + a | b +---+---- + 9 | 10 +(1 row) + +UPDATE Update_Test_d AS test_D SET test_D.a = 11, test_b.b = 12; +ERROR: column "test_b.b" of relation "Update_Test_d" does not exist +LINE 1: UPDATE Update_Test_d AS test_D SET test_D.a = 11, test_b.b =... + ^ +SELECT * FROM Update_Test_d; + a | b +---+---- + 9 | 10 +(1 row) + +UPDATE Update_Test_d test_D SET test_D.a = 11, test_b.b = 12; +ERROR: column "test_b.b" of relation "Update_Test_d" does not exist +LINE 1: UPDATE Update_Test_d test_D SET test_D.a = 11, test_b.b = 12... + ^ +SELECT * FROM Update_Test_d; + a | b +---+---- + 9 | 10 +(1 row) + +DROP TABLE Update_Test_c; +DROP TABLE Update_Test_d; +DROP TABLE Update_Test_d; +ERROR: table "Update_Test_d" does not exist +create table tbl_Update(a1 int,a2 varchar2(100)); +ALTER TABLE tbl_Update ADD PRIMARY KEY(a1); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "tbl_Update_pkey" for table "tbl_Update" +delete from tbl_Update; +insert into tbl_Update values(1,'a'); +insert into tbl_Update values(2,'b'); +insert into tbl_Update values(3,'c'); +insert into tbl_Update values(4,'d'); +insert into tbl_Update values(11,'AA'); +select * from tbl_Update order by a1; + a1 | a2 +----+---- + 1 | a + 2 | b + 3 | c + 4 | d + 11 | AA +(5 rows) + +create table sub_tab(T1 int,t2 varchar2(100)); +insert into sub_tab values(11,'AA'); +select * from sub_tab; + t1 | t2 +----+---- + 11 | AA +(1 row) + +update tbl_Update a set (a1,a2)=(100,'hello') from sub_tab t where t.T1=a.a1; +select * from tbl_Update order by a1; + a1 | a2 +-----+------- + 1 | a + 2 | b + 3 | c + 4 | d + 100 | hello +(5 rows) + +update tbl_Update a1 set (a1,a2)=(101,'hello world') from sub_tab t where t.T1=a1.a1; +select * from tbl_Update order by a1; + a1 | a2 +-----+------- + 1 | a + 2 | b + 3 | c + 4 | d + 100 | hello +(5 rows) + +drop table tbl_Update; +drop table sub_tab; +create table test_tbl_A(a int); +insert into test_tbl_A values(1); +select * from test_tbl_A; + a +--- + 1 +(1 row) + +update test_tbl_A a set a=2; +select * from test_tbl_A; + a +--- + 2 +(1 row) + +update test_tbl_A a set a=3 where a.a=2; +select * from test_tbl_A; + a +--- + 3 +(1 row) + +drop table test_tbl_A; +create table test_tbl_B(a int, b int); +insert into test_tbl_B values(1,2); +select * from test_tbl_B; + a | b +---+--- + 1 | 2 +(1 row) + +update test_tbl_B as a set (a,b)=(3,4); +update test_tbl_B set c = 100; +ERROR: column "c" of relation "test_tbl_B" does not exist +LINE 1: update test_tbl_B set c = 100; + ^ +select * from test_tbl_B; + a | b +---+--- + 3 | 4 +(1 row) + +update test_tbl_B as a set (a,b)=(5,6) where a.a=3 and a.b=4; +select * from test_tbl_B; + a | b +---+--- + 5 | 6 +(1 row) + +update test_tbl_B as a set (a.a, a.b)=(7,8) where a.a=5 and a.b=6; +select * from test_tbl_B; + a | b +---+--- + 7 | 8 +(1 row) + +drop table test_tbl_B; +CREATE TYPE complex AS (b int,c int); +CREATE TYPE complex AS (b int,c int); +ERROR: type "complex" already exists +create table test_tbl_C(a complex); +ALTER TABLE test_tbl_C ADD PRIMARY KEY(a); +NOTICE: ALTER TABLE / ADD PRIMARY KEY will create implicit index "test_tbl_C_pkey" for table "test_tbl_C" +insert into test_tbl_C values((1,2)); +select * from test_tbl_C; + a +------- + (1,2) +(1 row) + +update test_tbl_C col set col.a.b=(100); +select * from test_tbl_C; + a +--------- + (100,2) +(1 row) + +drop table test_tbl_C; +drop type complex; +-- Test multiple column set with GROUP BY of UPDATE +CREATE TABLE Update_Multiple_Set_01(a INT, b INT, c INT); +CREATE TABLE Update_Multiple_Set_02(a INT, b INT, c INT); +UPDATE Update_Multiple_Set_02 t2 SET (b, c) = (SELECT b, c FROM Update_Multiple_Set_01 T1 WHERE T1.a=t2.a GROUP BY 1, 2); +DROP TABLE Update_Multiple_Set_01; +DROP TABLE Update_Multiple_Set_02; +-- Test multiple column set with GROUP BY alias of UPDATE +drop table Usview08t; +ERROR: table "Usview08t" does not exist +drop table Offers_20050701; +ERROR: table "Offers_20050701" does not exist +create table Usview08t(location_id int, on_hand_unit_qty int, on_order_qty int); +create table Offers_20050701(location_id int null, visits int null); +insert into Usview08t values(1,3,5); +insert into Offers_20050701 values(2,4); +UPDATE Usview08t Table_008 SET (on_hand_unit_qty,on_order_qty) = (SELECT AVG(VISITS),154 c2 FROM Offers_20050701 GROUP BY c2); +select * from Usview08t; + location_id | on_hand_unit_qty | on_order_qty +-------------+------------------+-------------- + 1 | 4 | 154 +(1 row) + +UPDATE Usview08t t2 SET (t2.on_hand_unit_qty, t2.on_order_qty) = (SELECT AVG(VISITS),154 FROM Offers_20050701); +UPDATE Usview08t Table_008 SET (on_hand_unit_qty,on_hand_unit_qty) = (SELECT AVG(VISITS),154 c2 FROM Offers_20050701 GROUP BY c2); +ERROR: multiple assignments to same column "on_hand_unit_qty" +drop table Usview08t; +drop table Offers_20050701; +--Test table name reference or alias reference +create table Test (b int, a int); +insert into Test values(1,2); +update Test set Test.a=10; +update Test t set t.b=20; +select * from Test; + b | a +----+---- + 20 | 10 +(1 row) + +drop table Test; +create table Test(a int[3],b int); +insert into Test values('{1,2,3}',4); +update Test set Test.a='{10,20,30}'; +select * from Test; + a | b +------------+--- + {10,20,30} | 4 +(1 row) + +update Test t set t.a='{11,21,31}'; +select * from Test; + a | b +------------+--- + {11,21,31} | 4 +(1 row) + +update Test set a='{12,22,32}'; +select * from Test; + a | b +------------+--- + {12,22,32} | 4 +(1 row) + +update Test set a[1,2]='{13,23}'; +select * from Test; + a | b +------------+--- + {13,23,32} | 4 +(1 row) + +--must compatible with previous features, though not perfect +update Test set Test.a[1,2]='{14,24}'; +select * from Test; + a | b +------------+--- + {14,24,32} | 4 +(1 row) + +update Test t set t.a[1,2]='{15,25}'; +select * from Test; + a | b +------------+--- + {15,25,32} | 4 +(1 row) + +drop table Test; +create type newtype as(a int, b int); +create table Test(a newtype,b int); +insert into Test values(ROW(1,2),3); +update Test set Test.a=ROW(10,20); +select * from Test; + a | b +---------+--- + (10,20) | 3 +(1 row) + +update Test t set t.a=ROW(11,21); +select * from Test; + a | b +---------+--- + (11,21) | 3 +(1 row) + +--Ambiguous scene +--update field a of column a rather than column a of table a +update Test a set a.a=12; +NOTICE: update field 'a' of column 'a', though it's ambiguous. +--update field b of column a rather than column b of table a +update Test a set a.b=22; +NOTICE: update field 'b' of column 'a', though it's ambiguous. +select * from Test; + a | b +---------+--- + (12,22) | 3 +(1 row) + +--fail +update Test a set a.a=ROW(13,23); +NOTICE: update field 'a' of column 'a', though it's ambiguous. +ERROR: subfield "a" is of type integer but expression is of type record +LINE 1: update Test a set a.a=ROW(13,23); + ^ +HINT: You will need to rewrite or cast the expression. +CONTEXT: referenced column: a +update Test a set a.c=10; +NOTICE: update field 'c' of column 'a', though it's ambiguous. +ERROR: cannot assign to field "c" of column "a" because there is no such column in data type newtype +LINE 1: update Test a set a.c=10; + ^ +CONTEXT: referenced column: a +update Test b set b.c=10; +ERROR: column "c" of relation "Test" does not exist +LINE 1: update Test b set b.c=10; + ^ +--must compatible with previous features, though not perfect +update Test a set a.a.a=12; +select * from Test; + a | b +---------+--- + (12,22) | 3 +(1 row) + +drop table Test; +drop type newtype; +--Test update in merge into +create table test_D (a int, b int); +create table test_S (a int, b int); +insert into test_D values(generate_series(6,10),1); +insert into test_S values(generate_series(1,10),2); +merge into test_D using test_S on(test_D.a=test_S.a) when matched then update set test_D.b=test_S.b; +select * from test_D order by a; + a | b +----+--- + 6 | 2 + 7 | 2 + 8 | 2 + 9 | 2 + 10 | 2 +(5 rows) + +truncate table test_S; +insert into test_S values(generate_series(1,10),20); +merge into test_D d using test_S on(d.a=test_S.a) when matched then update set d.b=test_S.b; +select * from test_D order by a; + a | b +----+---- + 6 | 20 + 7 | 20 + 8 | 20 + 9 | 20 + 10 | 20 +(5 rows) + +drop table test_D; +drop table test_S; +create table test_D(a int[3],b int); +create table test_S(a int[3],b int); +insert into test_D values('{1,2,3}',4); +insert into test_S values('{10,20,30}',4); +merge into test_D using test_S on(test_D.b=test_S.b) when matched then update set test_D.a=test_S.a; +select * from test_D; + a | b +------------+--- + {10,20,30} | 4 +(1 row) + +truncate table test_S; +insert into test_S values('{11,21,31}',4); +merge into test_D d using test_S on(d.b=test_S.b) when matched then update set d.a=test_S.a; +select * from test_D; + a | b +------------+--- + {11,21,31} | 4 +(1 row) + +--must compatible with previous features, though not perfect +merge into test_D using test_S on(test_D.b=test_S.b) when matched then update set test_D.a[1,3]=test_S.a[1,3]; +select * from test_D; + a | b +------------+--- + {11,21,31} | 4 +(1 row) + +merge into test_D d using test_S on(d.b=test_S.b) when matched then update set d.a[1,3]=test_S.a[1,3]; +select * from test_D; + a | b +------------+--- + {11,21,31} | 4 +(1 row) + +drop table test_D; +drop table test_S; +create type newtype as(a int,b int); +create table test_D(a newtype, b int); +create table test_S(a newtype, b int); +insert into test_D values(ROW(1,2),3); +insert into test_S values(ROW(10,20),3); +merge into test_D using test_S on(test_D.b=test_S.b) when matched then update set test_D.a=test_S.a; +select * from test_D; + a | b +---------+--- + (10,20) | 3 +(1 row) + +truncate table test_S; +insert into test_S values(ROW(11,12),3); +merge into test_D d using test_S on(d.b=test_S.b) when matched then update set d.a=test_S.a; +select * from test_D; + a | b +---------+--- + (11,12) | 3 +(1 row) + +truncate table test_S; +insert into test_S values(ROW(22,22),3); +merge into test_D a using test_S on(a.b=test_S.b) when matched then update set a.a=21; +NOTICE: update field 'a' of column 'a', though it's ambiguous. +merge into test_D a using test_S on(a.b=test_S.b) when matched then update set a.b=22; +NOTICE: update field 'b' of column 'a', though it's ambiguous. +select * from test_D; + a | b +---------+--- + (21,22) | 3 +(1 row) + +--fail +merge into test_D a using test_S on(a.b=test_S.b) when matched then update set a.a=test_S.a; +NOTICE: update field 'a' of column 'a', though it's ambiguous. +ERROR: subfield "a" is of type integer but expression is of type newtype +LINE 1: ...t_S on(a.b=test_S.b) when matched then update set a.a=test_S... + ^ +HINT: You will need to rewrite or cast the expression. +CONTEXT: referenced column: a +--must compatible with previous features, though not perfect +merge into test_D using test_S on(test_D.b=test_S.b) when matched then update set test_D.a.a=test_S.b; +select * from test_D; + a | b +--------+--- + (3,22) | 3 +(1 row) + +merge into test_D d using test_S on(d.b=test_S.b) when matched then update set d.a.a=test_S.b; +select * from test_D; + a | b +--------+--- + (3,22) | 3 +(1 row) + +drop table test_S; +drop table test_D; +drop type newtype; +-- Test update multiple entries for the same column with subselect +create table Test (a int[2], b int); +insert into Test values('{1,2}',3); +update Test set (a[1],a[2])=(select 10,20); +select * from Test; + a | b +---------+--- + {10,20} | 3 +(1 row) + +drop table Test; +create type nt as(a int,b int); +create table Test(a nt,b nt,c int); +insert into Test values(row(1,2),row(3,4),5); +update Test set (a.b,b.b)=(select 20,40); +select * from Test; + a | b | c +--------+--------+--- + (1,20) | (3,40) | 5 +(1 row) + +drop table Test; +drop type nt; +-- Test comment in subselect of update +create table Test(a int,b int); +insert into Test values(1,2); +update Test set (a)=(select /*comment*/10); +select * from Test; + a | b +----+--- + 10 | 2 +(1 row) + +update Test set (a)=(select /*+comment*/20); +select * from Test; + a | b +----+--- + 20 | 2 +(1 row) + +drop table Test; +--Test update multiple fields of column which using composite type at once +create type nt as(a int,b int); +create table AA (a nt, b int,c char); +explain (verbose on, costs off) insert into AA values(ROW(1,2),3,'4'); + QUERY PLAN +------------------------------------------------- + Insert on public."AA" + -> Result + Output: ROW(1, 2), 3, '4'::character(1) +(3 rows) + +insert into AA values(ROW(1,2),3,'4'); +explain (verbose on, costs off) update AA set a.a=10,a.b=20 where c='4'; + QUERY PLAN +----------------------------------------- + Update on public."AA" + -> Seq Scan on public."AA" + Output: ROW(10, 20), b, c, ctid + Filter: ("AA".c = '4'::bpchar) +(4 rows) + +update AA set a.a=10,a.b=20 where c='4'; +select * from AA; + a | b | c +---------+---+--- + (10,20) | 3 | 4 +(1 row) + +drop table AA; +drop type nt; +--Test update multiple values of of an array at once +create table Test (a int[2], b int,c char); +insert into Test values('{1,2}',3,'4'); +explain (verbose on, costs off) update Test set a[1]=100,a[2]=200 where c='4'; + QUERY PLAN +----------------------------------------------------- + Update on public."Test" + -> Seq Scan on public."Test" + Output: (a[1] := 100)[2] := 200, b, c, ctid + Filter: ("Test".c = '4'::bpchar) +(4 rows) + +update Test set a[1]=100,a[2]=200 where c='4'; +select * from Test; + a | b | c +-----------+---+--- + {100,200} | 3 | 4 +(1 row) + +explain (verbose on, costs off) update Test set a[1,2]='{101,201}' where c='4'; + QUERY PLAN +-------------------------------------------------------------- + Update on public."Test" + -> Seq Scan on public."Test" + Output: a[1:2] := '{101,201}'::integer[], b, c, ctid + Filter: ("Test".c = '4'::bpchar) +(4 rows) + +update Test set a[1,2]='{101,201}' where c='4'; +select * from Test; + a | b | c +-----------+---+--- + {101,201} | 3 | 4 +(1 row) + +explain (verbose on, costs off) insert into Test (a[1,2],b,c) values('{113,114}',4,'5'); + QUERY PLAN +---------------------------------------------------------------------------------------- + Insert on public."Test" + -> Result + Output: (NULL::integer[])[1:2] := '{113,114}'::integer[], 4, '5'::character(1) +(3 rows) + +insert into Test (a[1,2],b,c) values('{113,114}',4,'5'); +select * from Test order by 3; + a | b | c +-----------+---+--- + {101,201} | 3 | 4 + {113,114} | 4 | 5 +(2 rows) + +select a[1,2] from Test where c='4'; + a +----------- + {101,201} +(1 row) + +explain (verbose on, costs off) insert into Test (a[1],a[2],b,c)values(1,2,3,'6'); + QUERY PLAN +--------------------------------------------------------------------------- + Insert on public."Test" + -> Result + Output: ((NULL::integer[])[1] := 1)[2] := 2, 3, '6'::character(1) +(3 rows) + +insert into Test (a[1],a[2],b,c)values(1,2,3,'6'); +select * from Test order by 3; + a | b | c +-----------+---+--- + {101,201} | 3 | 4 + {113,114} | 4 | 5 + {1,2} | 3 | 6 +(3 rows) + +explain (verbose on, costs off) insert into Test (a[1:2],b,c)values('{1,2}',3,'7'); + QUERY PLAN +------------------------------------------------------------------------------------ + Insert on public."Test" + -> Result + Output: (NULL::integer[])[1:2] := '{1,2}'::integer[], 3, '7'::character(1) +(3 rows) + +insert into Test (a[1:2],b,c)values('{1,2}',3,'7'); +select * from Test order by 3; + a | b | c +-----------+---+--- + {101,201} | 3 | 4 + {113,114} | 4 | 5 + {1,2} | 3 | 6 + {1,2} | 3 | 7 +(4 rows) + +explain (verbose on, costs off) update Test set a[1:2]='{10,20}' where c='7'; + QUERY PLAN +------------------------------------------------------------ + Update on public."Test" + -> Seq Scan on public."Test" + Output: a[1:2] := '{10,20}'::integer[], b, c, ctid + Filter: ("Test".c = '7'::bpchar) +(4 rows) + +update Test set a[1:2]='{10,20}' where c='7'; +select * from Test order by 3; + a | b | c +-----------+---+--- + {101,201} | 3 | 4 + {113,114} | 4 | 5 + {1,2} | 3 | 6 + {10,20} | 3 | 7 +(4 rows) + +drop table Test; diff --git a/contrib/dolphin/expected/case_sensitive_test/vacuum.out b/contrib/dolphin/expected/case_sensitive_test/vacuum.out new file mode 100644 index 0000000000000000000000000000000000000000..d006a0cdaf8d371fea7ec907ae1ef932368b5cbb --- /dev/null +++ b/contrib/dolphin/expected/case_sensitive_test/vacuum.out @@ -0,0 +1,81 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- VACUUM +-- +CREATE TABLE Vactst (i INT); +INSERT INTO Vactst VALUES (1); +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst VALUES (0); +SELECT count(*) FROM Vactst; + count +------- + 2049 +(1 row) + +DELETE FROM Vactst WHERE i != 0; +SELECT * FROM Vactst; + i +--- + 0 +(1 row) + +VACUUM FULL Vactst; +UPDATE Vactst SET i = i + 1; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst VALUES (0); +SELECT count(*) FROM Vactst; + count +------- + 2049 +(1 row) + +DELETE FROM Vactst WHERE i != 0; +VACUUM (FULL) Vactst; +DELETE FROM Vactst; +SELECT * FROM Vactst; + i +--- +(0 rows) + +VACUUM (FULL, FREEZE) Vactst; +VACUUM (ANALYZE, FULL) Vactst; +CREATE TABLE Vaccluster (i INT PRIMARY KEY); +NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "Vaccluster_pkey" for table "Vaccluster" +ALTER TABLE Vaccluster CLUSTER ON Vaccluster_pkey; +ERROR: index "vaccluster_pkey" for table "Vaccluster" does not exist +INSERT INTO Vaccluster SELECT * FROM Vactst; +CLUSTER Vaccluster; +ERROR: there is no previously clustered index for table "Vaccluster" +set xc_maintenance_mode = on; +VACUUM FULL pg_am; +VACUUM FULL pg_class; +VACUUM FULL pg_database; +set xc_maintenance_mode = off; +VACUUM FULL Vaccluster; +VACUUM FULL Vactst; +DROP TABLE Vaccluster; +DROP TABLE Vactst; +CREATE TABLE "~!@#$%^&*+-=`,./\';:{}[]|0(>_<)0"(A TEXT); +VACUUM "~!@#$%^&*+-=`,./\';:{}[]|0(>_<)0"; +DROP TABLE "~!@#$%^&*+-=`,./\';:{}[]|0(>_<)0"; diff --git a/contrib/dolphin/include/plugin_postgres.h b/contrib/dolphin/include/plugin_postgres.h index 16ad2cdd8aceb89bec93ca94cd6a69b1cb1b1f38..2c8b4394fc2c10afca76d19755c2e0b77e209bc4 100644 --- a/contrib/dolphin/include/plugin_postgres.h +++ b/contrib/dolphin/include/plugin_postgres.h @@ -64,6 +64,7 @@ typedef struct BSqlPluginContext { unsigned int sqlModeFlags; List* lockNameList; double b_db_timestamp; + int lower_case_table_names; } bSqlPluginContext; BSqlPluginContext* GetSessionContext(); diff --git a/contrib/dolphin/input/case_sensitive_test/clean_env.source b/contrib/dolphin/input/case_sensitive_test/clean_env.source new file mode 100644 index 0000000000000000000000000000000000000000..31bfe7cbbc117faa2cc8cc15d1ae3f24faa81154 --- /dev/null +++ b/contrib/dolphin/input/case_sensitive_test/clean_env.source @@ -0,0 +1,2 @@ +\c postgres +DROP DATABASE table_name_test_db; \ No newline at end of file diff --git a/contrib/dolphin/input/case_sensitive_test/create_env.source b/contrib/dolphin/input/case_sensitive_test/create_env.source new file mode 100644 index 0000000000000000000000000000000000000000..b6433953e57afd7a86dcb95284f3a42e12b43d65 --- /dev/null +++ b/contrib/dolphin/input/case_sensitive_test/create_env.source @@ -0,0 +1,60 @@ +DROP DATABASE IF EXISTS table_name_test_db; +CREATE DATABASE table_name_test_db dbcompatibility 'b'; +\c table_name_test_db +CREATE FUNCTION check_primary_key () + RETURNS trigger + AS '@libdir@/refint@DLSUFFIX@' + LANGUAGE C NOT FENCED; +CREATE FUNCTION check_foreign_key () + RETURNS trigger + AS '@libdir@/refint@DLSUFFIX@' + LANGUAGE C NOT FENCED; +CREATE FUNCTION autoinc () + RETURNS trigger + AS '@libdir@/autoinc@DLSUFFIX@' + LANGUAGE C NOT FENCED; +CREATE FUNCTION funny_dup17 () + RETURNS trigger + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C NOT FENCED; +CREATE FUNCTION ttdummy () + RETURNS trigger + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C NOT FENCED; +CREATE FUNCTION set_ttdummy (int4) + RETURNS int4 + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C STRICT NOT FENCED; +CREATE FUNCTION test_atomic_ops() + RETURNS bool + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C STRICT NOT FENCED; + +create table point (c1 point) with (storage_type=USTORE); + +CREATE TABLE point_tbl(f1 point); + +INSERT INTO point_tbl(f1) VALUES ('(0.0,0.0)'); + +INSERT INTO point_tbl(f1) VALUES ('(-10.0,0.0)'); + +INSERT INTO point_tbl(f1) VALUES ('(-3.0,4.0)'); + +INSERT INTO point_tbl(f1) VALUES ('(5.1, 34.5)'); + +INSERT INTO point_tbl(f1) VALUES ('(-5.0,-12.0)'); + +-- bad format points +INSERT INTO point_tbl(f1) VALUES ('asdfasdf'); + +INSERT INTO point_tbl(f1) VALUES ('10.0,10.0'); + +INSERT INTO point_tbl(f1) VALUES ('(10.0 10.0)'); + +INSERT INTO point_tbl(f1) VALUES ('(10.0,10.0'); + +-- Test that GiST indexes provide same behavior as sequential scan +CREATE TEMP TABLE point_gist_tbl(f1 point); +INSERT INTO point_gist_tbl SELECT '(0,0)' FROM generate_series(0,1000); +CREATE INDEX point_gist_tbl_index ON point_gist_tbl USING gist (f1); +INSERT INTO point_gist_tbl VALUES ('(0.0000009,0.0000009)'); diff --git a/contrib/dolphin/output/case_sensitive_test/clean_env.source b/contrib/dolphin/output/case_sensitive_test/clean_env.source new file mode 100644 index 0000000000000000000000000000000000000000..f0ce30555bc4838cdf1e5c8da2a8a04fa4a56cab --- /dev/null +++ b/contrib/dolphin/output/case_sensitive_test/clean_env.source @@ -0,0 +1,2 @@ +\c postgres +DROP DATABASE table_name_test_db; diff --git a/contrib/dolphin/output/case_sensitive_test/create_env.source b/contrib/dolphin/output/case_sensitive_test/create_env.source new file mode 100644 index 0000000000000000000000000000000000000000..0944e8a9446b1c2833dcc7fe24d5109fb7fd62fd --- /dev/null +++ b/contrib/dolphin/output/case_sensitive_test/create_env.source @@ -0,0 +1,61 @@ +DROP DATABASE IF EXISTS table_name_test_db; +NOTICE: database "table_name_test_db" does not exist, skipping +CREATE DATABASE table_name_test_db dbcompatibility 'b'; +\c table_name_test_db +CREATE FUNCTION check_primary_key () + RETURNS trigger + AS '@libdir@/refint@DLSUFFIX@' + LANGUAGE C NOT FENCED; +CREATE FUNCTION check_foreign_key () + RETURNS trigger + AS '@libdir@/refint@DLSUFFIX@' + LANGUAGE C NOT FENCED; +CREATE FUNCTION autoinc () + RETURNS trigger + AS '@libdir@/autoinc@DLSUFFIX@' + LANGUAGE C NOT FENCED; +CREATE FUNCTION funny_dup17 () + RETURNS trigger + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C NOT FENCED; +CREATE FUNCTION ttdummy () + RETURNS trigger + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C NOT FENCED; +CREATE FUNCTION set_ttdummy (int4) + RETURNS int4 + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C STRICT NOT FENCED; +CREATE FUNCTION test_atomic_ops() + RETURNS bool + AS '@libdir@/regress@DLSUFFIX@' + LANGUAGE C STRICT NOT FENCED; +create table point (c1 point) with (storage_type=USTORE); +CREATE TABLE point_tbl(f1 point); +INSERT INTO point_tbl(f1) VALUES ('(0.0,0.0)'); +INSERT INTO point_tbl(f1) VALUES ('(-10.0,0.0)'); +INSERT INTO point_tbl(f1) VALUES ('(-3.0,4.0)'); +INSERT INTO point_tbl(f1) VALUES ('(5.1, 34.5)'); +INSERT INTO point_tbl(f1) VALUES ('(-5.0,-12.0)'); +-- bad format points +INSERT INTO point_tbl(f1) VALUES ('asdfasdf'); +ERROR: invalid input syntax for type point: "asdfasdf" +LINE 1: INSERT INTO point_tbl(f1) VALUES ('asdfasdf'); + ^ +CONTEXT: referenced column: f1 +INSERT INTO point_tbl(f1) VALUES ('10.0,10.0'); +INSERT INTO point_tbl(f1) VALUES ('(10.0 10.0)'); +ERROR: invalid input syntax for type point: "(10.0 10.0)" +LINE 1: INSERT INTO point_tbl(f1) VALUES ('(10.0 10.0)'); + ^ +CONTEXT: referenced column: f1 +INSERT INTO point_tbl(f1) VALUES ('(10.0,10.0'); +ERROR: invalid input syntax for type point: "(10.0,10.0" +LINE 1: INSERT INTO point_tbl(f1) VALUES ('(10.0,10.0'); + ^ +CONTEXT: referenced column: f1 +-- Test that GiST indexes provide same behavior as sequential scan +CREATE TEMP TABLE point_gist_tbl(f1 point); +INSERT INTO point_gist_tbl SELECT '(0,0)' FROM generate_series(0,1000); +CREATE INDEX point_gist_tbl_index ON point_gist_tbl USING gist (f1); +INSERT INTO point_gist_tbl VALUES ('(0.0000009,0.0000009)'); diff --git a/contrib/dolphin/parallel_schedule_dolphin b/contrib/dolphin/parallel_schedule_dolphin index 38952044f44dab563b9e3e3f7b747072179e232d..e18d9567852c89b3a77eb3f1e11f41d5e859c6ca 100644 --- a/contrib/dolphin/parallel_schedule_dolphin +++ b/contrib/dolphin/parallel_schedule_dolphin @@ -76,3 +76,19 @@ test: test_table_index test: db_b_date_time_functions test: builtin_funcs/b_compatibility_time_funcs + +# case sensitive test, do not insert test case */ +test: case_sensitive_test/create_env + +test: case_sensitive_test/create_table case_sensitive_test/create_table_like case_sensitive_test/create_foreign_table case_sensitive_test/cluster case_sensitive_test/temp case_sensitive_test/rowlevelsecurity + +test: case_sensitive_test/single_node_foreign_key case_sensitive_test/create_index case_sensitive_test/insert case_sensitive_test/update case_sensitive_test/delete case_sensitive_test/vacuum case_sensitive_test/analyze_commands case_sensitive_test/single_node_triggers + +test: case_sensitive_test/alter_table case_sensitive_test/reindex_internal + +test: case_sensitive_test/drop + +test: case_sensitive_test/clean_env + +test: case_sensitive_test/role_test +# case sensitive test end diff --git a/contrib/dolphin/plugin_parser/gram.y b/contrib/dolphin/plugin_parser/gram.y index 2033a6239bc0085452fea992d6bd3a600caac568..dd1914112c56a2814f50eb984c9dea20c9216f1e 100644 --- a/contrib/dolphin/plugin_parser/gram.y +++ b/contrib/dolphin/plugin_parser/gram.y @@ -258,6 +258,13 @@ typedef struct OptLikeWhere Node *like_or_where; } OptLikeWhere; +typedef struct DolphinString +{ + Node* node; + char* str; + bool is_quoted; +} DolphinString; + /* ConstraintAttributeSpec yields an integer bitmask of these flags: */ #define CAS_NOT_DEFERRABLE 0x01 #define CAS_DEFERRABLE 0x02 @@ -276,6 +283,7 @@ typedef struct OptLikeWhere #define parser_yyerror(msg) scanner_yyerror(msg, yyscanner) #define parser_errposition(pos) scanner_errposition(pos, yyscanner) +#define is_quoted() pg_yyget_extra(yyscanner)->core_yy_extra.ident_quoted static long conv_bit_to_int(A_Const* bit_str); static void fix_bw_type(A_Const* bw_arg1, A_Const* bw_arg2, A_Const* bw_arg3); @@ -294,6 +302,7 @@ static Node *makeBitStringConst(char *str, int location); Node *makeAConst(Value *v, int location); Node *makeBoolAConst(bool state, int location); static void check_qualified_name(List *names, core_yyscan_t yyscanner); +static void check_dolphin_qualified_name(List *names, core_yyscan_t yyscanner); static List *check_func_name(List *names, core_yyscan_t yyscanner); static List *check_setting_name(List *names, core_yyscan_t yyscanner); static List *check_indirection(List *indirection, core_yyscan_t yyscanner); @@ -384,6 +393,11 @@ static bool CheckWhetherInColList(char *colname, List *col_list); static int GetFillerColIndex(char *filler_col_name, List *col_list); static void RemoveFillerCol(List *filler_list, List *col_list); static int errstate; +static char* downcase_str(const char* ident, bool is_quoted); +static DolphinString* makeDolphinStringByChar(char* str, bool is_quoted); +static DolphinString* makeDolphinStringByNode(Node* node, bool is_quoted); +static List* GetNameListFromDolphinString(List* dolphinStringList); +static char* GetDolphinObjName(const char* string, bool is_quoted); %} %define api.pure @@ -448,6 +462,7 @@ static int errstate; struct CreateIndexOptions *createindexoptions; struct SingleIndexOption *singleindexoption; struct IndexMethodRelationClause *indexmethodrelationclause; + struct DolphinString *dolphinString; } %type CreateOption CreateIfNotExistsOption CreateAsOption %type CreateOptionList CreateIfNotExistsOptionList CreateAsOptionList @@ -581,14 +596,14 @@ static int errstate; %type copy_file_name database_name access_method_clause access_method attr_name name namedata_string fdwName cursor_name file_name - index_name cluster_index_specification + index_name cluster_index_specification dolphin_index_name pgxcnode_name pgxcgroup_name resource_pool_name workload_group_name application_name password_string hint_string -%type func_name func_name_opt_arg pkg_name handler_name qual_Op qual_all_Op subquery_Op +%type func_name func_name_opt_arg pkg_name handler_name qual_Op qual_all_Op subquery_Op dolphin_func_name opt_class opt_inline_handler opt_validator validator_clause opt_collate -%type qualified_name insert_target OptConstrFromTable opt_index_name insert_partition_clause update_delete_partition_clause +%type qualified_name insert_target OptConstrFromTable opt_index_name insert_partition_clause update_delete_partition_clause dolphin_qualified_name %type all_Op MathOp OptDbName @@ -626,12 +641,12 @@ static int errstate; opt_column_list columnList opt_name_list opt_analyze_column_define opt_multi_name_list opt_include_without_empty opt_c_include index_including_params sort_clause opt_sort_clause sortby_list index_params table_index_elems index_options - name_list from_clause from_list opt_array_bounds - qualified_name_list any_name any_name_list - any_operator expr_list attrs callfunc_args callfunc_args_or_empty + name_list from_clause from_list opt_array_bounds dolphin_name_list + qualified_name_list any_name any_name_list dolphin_qualified_name_list dolphin_any_name dolphin_any_name_list + any_operator expr_list attrs callfunc_args callfunc_args_or_empty dolphin_attrs target_list insert_column_list set_target_list set_clause_list set_clause multiple_set_clause - ctext_expr_list ctext_row def_list tsconf_def_list indirection opt_indirection + ctext_expr_list ctext_row def_list tsconf_def_list indirection opt_indirection dolphin_indirection opt_dolphin_indirection reloption_list tblspc_option_list cfoption_list group_clause TriggerFuncArgs select_limit opt_select_limit opt_delete_limit opclass_item_list opclass_drop_list opclass_purpose opt_opfamily transaction_mode_list_or_empty @@ -695,7 +710,7 @@ static int errstate; %type copy_from %type opt_column event cursor_options opt_hold opt_set_data -%type reindex_type drop_type comment_type security_label_type +%type reindex_type drop_type comment_type security_label_type dolphin_comment_type %type fetch_args limit_clause select_limit_value offset_clause select_offset_value @@ -732,7 +747,7 @@ static int errstate; %type ctext_expr %type NumericOnly %type NumericOnly_list -%type alias_clause opt_alias_clause +%type alias_clause opt_alias_clause dolphin_alias_clause opt_dolphin_alias_clause %type sortby %type index_elem table_index_elem %type table_ref @@ -776,6 +791,7 @@ static int errstate; %type var_list %type ColId ColLabel var_name type_function_name param_name user opt_password opt_replace show_index_schema_opt ColIdForTableElement %type var_value zone_value +%type DolphinColId DolphinColLabel dolphin_indirection_el %type unreserved_keyword type_func_name_keyword unreserved_keyword_without_key %type col_name_keyword reserved_keyword @@ -925,6 +941,7 @@ static int errstate; %type into_empty opt_temporary opt_values_in replace_empty %type compression_args %type opt_ignore +%type normal_ident /* * Non-keyword token types. These are hard-wired into the "flex" lexer. @@ -1616,7 +1633,7 @@ AlterOptRoleElem: { $$ = makeDefElem("rolemembers", (Node *)$2); } - | IDENT + | normal_ident { /* * We handle identifiers that aren't parser keywords with @@ -1885,7 +1902,7 @@ DropRoleStmt: *****************************************************************************/ DropUserStmt: - DROP USER name_list opt_drop_behavior + DROP USER dolphin_name_list opt_drop_behavior { DropRoleStmt *n = makeNode(DropRoleStmt); n->missing_ok = FALSE; @@ -1894,7 +1911,7 @@ DropUserStmt: n->behavior = $4; $$ = (Node *)n; } - | DROP USER IF_P EXISTS name_list opt_drop_behavior + | DROP USER IF_P EXISTS dolphin_name_list opt_drop_behavior { DropRoleStmt *n = makeNode(DropRoleStmt); n->roles = $5; @@ -2501,7 +2518,7 @@ zone_value: { $$ = makeStringConst($1, @1); } - | IDENT + | normal_ident { $$ = makeStringConst($1, @1); } @@ -2660,7 +2677,7 @@ VariableShowStmt: SelectStmt *n = makeShowTablesQuery(TRUE, $4, $5->like_or_where, $5->is_like); $$ = (Node *) n; } - | SHOW opt_full_fields from_in qualified_name OptDbName OptLikeOrWhere + | SHOW opt_full_fields from_in dolphin_qualified_name OptDbName OptLikeOrWhere { SelectStmt *n = makeShowColumnsQuery($4->schemaname, $4->relname, $5, $2, $6->is_like, $6->like_or_where); $$ = (Node *)n; @@ -2707,7 +2724,7 @@ VariableShowStmt: n->name = "all"; $$ = (Node *) n; } - | SHOW show_index_opt from_in qualified_name show_index_schema_opt where_clause + | SHOW show_index_opt from_in dolphin_qualified_name show_index_schema_opt where_clause { SelectStmt *s = makeShowIndexQuery($5 ? $5 : $4->schemaname, $4->relname, $6); $$ = (Node*)s; @@ -3707,7 +3724,7 @@ alter_table_cmd: n->def = $3; $$ = (Node *)n; } - | ADD_P TABLE qualified_name + | ADD_P TABLE dolphin_qualified_name { AlterTableCmd *n = makeNode(AlterTableCmd); AddTableIntoCBIState *s = makeNode(AddTableIntoCBIState); @@ -4055,7 +4072,7 @@ alter_table_cmd: $$ = (Node *)n; } /* ALTER TABLE INHERIT */ - | INHERIT qualified_name + | INHERIT dolphin_qualified_name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_AddInherit; @@ -4063,7 +4080,7 @@ alter_table_cmd: $$ = (Node *)n; } /* ALTER TABLE NO INHERIT */ - | NO INHERIT qualified_name + | NO INHERIT dolphin_qualified_name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_DropInherit; @@ -4184,7 +4201,7 @@ alter_table_cmd: $$ = (Node *)n; } /* ALTER TABLE UPDATE SLICE LIKE (reftalbename), only used for redis range/list distribution table */ - | UPDATE SLICE LIKE qualified_name + | UPDATE SLICE LIKE dolphin_qualified_name { AlterTableCmd *n = makeNode(AlterTableCmd); n->subtype = AT_UpdateSliceLike; @@ -4318,7 +4335,7 @@ reloption_elem: } | ColLabel '=' ROW { - $$ = makeDefElem($1, (Node *) makeString(pstrdup($3))); + $$ = makeDefElem($1, (Node *) makeString(downcase_str(pstrdup($3), false))); } | ColLabel { @@ -4403,7 +4420,7 @@ split_dest_rangesubpartition_define_list: /*support b_database syntax related with partition*/ AlterPartitionRebuildStmt: - ALTER TABLE qualified_name REBUILD_PARTITION partition_name_list + ALTER TABLE dolphin_qualified_name REBUILD_PARTITION partition_name_list { FuncCall *n = makeNode(FuncCall); n->funcname = list_make1(makeString("rebuild_partition")); @@ -4422,7 +4439,7 @@ AlterPartitionRebuildStmt: sel->targetList = list_make1(rtg); $$ = (Node *)sel; } - | ALTER TABLE qualified_name REBUILD_PARTITION ALL + | ALTER TABLE dolphin_qualified_name REBUILD_PARTITION ALL { FuncCall *n = makeNode(FuncCall); n->funcname = list_make1(makeString("rebuild_partition")); @@ -4444,7 +4461,7 @@ AlterPartitionRebuildStmt: ; AlterPartitionRemoveStmt: - ALTER TABLE qualified_name REMOVE PARTITIONING + ALTER TABLE dolphin_qualified_name REMOVE PARTITIONING { FuncCall *n = makeNode(FuncCall); n->funcname = list_make1(makeString("remove_partitioning")); @@ -4466,22 +4483,22 @@ AlterPartitionRemoveStmt: ; AlterPartitionCheckStmt: - ALTER TABLE qualified_name CHECK PARTITION partition_name_list { $$=NULL; } - | ALTER TABLE qualified_name CHECK PARTITION ALL { $$=NULL; } + ALTER TABLE dolphin_qualified_name CHECK PARTITION partition_name_list { $$=NULL; } + | ALTER TABLE dolphin_qualified_name CHECK PARTITION ALL { $$=NULL; } ; AlterPartitionRepairStmt: - ALTER TABLE qualified_name REPAIR PARTITION partition_name_list { $$=NULL; } - | ALTER TABLE qualified_name REPAIR PARTITION ALL { $$=NULL; } + ALTER TABLE dolphin_qualified_name REPAIR PARTITION partition_name_list { $$=NULL; } + | ALTER TABLE dolphin_qualified_name REPAIR PARTITION ALL { $$=NULL; } ; AlterPartitionOptimizeStmt: - ALTER TABLE qualified_name OPTIMIZE PARTITION partition_name_list { $$=NULL; } - | ALTER TABLE qualified_name OPTIMIZE PARTITION ALL { $$=NULL; } + ALTER TABLE dolphin_qualified_name OPTIMIZE PARTITION partition_name_list { $$=NULL; } + | ALTER TABLE dolphin_qualified_name OPTIMIZE PARTITION ALL { $$=NULL; } ; AnalyzePartitionStmt: - ALTER TABLE qualified_name analyze_keyword opt_verbose opt_name_list PARTITION partition_name_list + ALTER TABLE dolphin_qualified_name analyze_keyword opt_verbose opt_name_list PARTITION partition_name_list { List* arglist = NIL; arglist = lcons(makeStringConst($3->relname, @3), $8); @@ -4504,7 +4521,7 @@ AnalyzePartitionStmt: sel->targetList = list_make1(rtg); $$ = (Node *)sel; } - | ALTER TABLE qualified_name analyze_keyword opt_verbose opt_name_list PARTITION ALL + | ALTER TABLE dolphin_qualified_name analyze_keyword opt_verbose opt_name_list PARTITION ALL { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_ANALYZE; @@ -5119,7 +5136,7 @@ ClosePortalStmt: * *****************************************************************************/ -CopyStmt: COPY BINARY qualified_name opt_column_list opt_oids +CopyStmt: COPY BINARY dolphin_qualified_name opt_column_list opt_oids copy_from copy_file_name opt_load opt_useeof copy_delimiter opt_noescaping OptCopyLogError OptCopyRejectLimit opt_with copy_options opt_processed { @@ -5161,7 +5178,7 @@ CopyStmt: COPY BINARY qualified_name opt_column_list opt_oids u_sess->parser_cxt.is_load_copy = false; u_sess->parser_cxt.col_list = NULL; } - | COPY qualified_name opt_column_list opt_oids + | COPY dolphin_qualified_name opt_column_list opt_oids copy_from copy_file_name opt_load opt_useeof copy_delimiter opt_noescaping OptCopyLogError OptCopyRejectLimit opt_with copy_options opt_processed { @@ -5690,7 +5707,7 @@ CreateStreamStmt: * *****************************************************************************/ PurgeStmt: - PURGE TABLE qualified_name + PURGE TABLE dolphin_qualified_name { TcapFeatureEnsure(); PurgeStmt *n = makeNode(PurgeStmt); @@ -5742,7 +5759,7 @@ PurgeStmt: *****************************************************************************/ TimeCapsuleStmt: - TIMECAPSULE TABLE qualified_name TO opt_timecapsule_clause + TIMECAPSULE TABLE dolphin_qualified_name TO opt_timecapsule_clause { TcapFeatureEnsure(); TimeCapsuleStmt *n = makeNode(TimeCapsuleStmt); @@ -5756,7 +5773,7 @@ TimeCapsuleStmt: $$ = (Node *) n; } - | TIMECAPSULE TABLE qualified_name TO BEFORE DROP opt_rename + | TIMECAPSULE TABLE dolphin_qualified_name TO BEFORE DROP opt_rename { TcapFeatureEnsure(); TimeCapsuleStmt *n = makeNode(TimeCapsuleStmt); @@ -5766,7 +5783,7 @@ TimeCapsuleStmt: $$ = (Node *) n; } - | TIMECAPSULE TABLE qualified_name TO BEFORE TRUNCATE + | TIMECAPSULE TABLE dolphin_qualified_name TO BEFORE TRUNCATE { TcapFeatureEnsure(); TimeCapsuleStmt *n = makeNode(TimeCapsuleStmt); @@ -5983,7 +6000,7 @@ CreateAsOption: } ; -CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' +CreateStmt: CREATE OptTemp TABLE dolphin_qualified_name '(' OptTableElementList ')' CreateOptionList { CreateStmt *n = makeNode(CreateStmt); @@ -6011,7 +6028,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' } $$ = (Node *)n; } - | CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' + | CREATE OptTemp TABLE dolphin_qualified_name '(' OptTableElementList ')' { CreateStmt *n = makeNode(CreateStmt); $4->relpersistence = $2; @@ -6033,7 +6050,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->internalData = NULL; $$ = (Node *)n; } - | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name '(' + | CREATE OptTemp TABLE IF_P NOT EXISTS dolphin_qualified_name '(' OptTableElementList ')' CreateIfNotExistsOptionList { CreateStmt *n = makeNode(CreateStmt); @@ -6060,7 +6077,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' } $$ = (Node *)n; } - | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name '(' + | CREATE OptTemp TABLE IF_P NOT EXISTS dolphin_qualified_name '(' OptTableElementList ')' { CreateStmt *n = makeNode(CreateStmt); @@ -6082,7 +6099,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' n->internalData = NULL; $$ = (Node *)n; } - | CREATE OptTemp TABLE qualified_name OF any_name + | CREATE OptTemp TABLE dolphin_qualified_name OF any_name OptTypedTableElementList OptWith OnCommitOption OptCompress OptPartitionElement /* PGXC_BEGIN */ OptDistributeBy OptSubCluster @@ -6112,7 +6129,7 @@ CreateStmt: CREATE OptTemp TABLE qualified_name '(' OptTableElementList ')' } $$ = (Node *)n; } - | CREATE OptTemp TABLE IF_P NOT EXISTS qualified_name OF any_name + | CREATE OptTemp TABLE IF_P NOT EXISTS dolphin_qualified_name OF any_name OptTypedTableElementList OptWith OnCommitOption OptCompress OptPartitionElement /* PGXC_BEGIN */ OptDistributeBy OptSubCluster @@ -6185,7 +6202,7 @@ opt_engine_without_empty: } ; -compression_args: IDENT { $$ = $1; } +compression_args: normal_ident { $$ = $1; } | Sconst { $$ = $1; } | NONE { $$ = "none"; } ; @@ -6323,7 +6340,7 @@ list_partitioning_clause: ; hash_partitioning_clause: - PARTITION BY IDENT '(' column_item_list ')' subpartitioning_clause + PARTITION BY normal_ident '(' column_item_list ')' subpartitioning_clause '(' hash_partition_definition_list ')' opt_row_movement_clause { #ifdef ENABLE_MULTIPLE_NODES @@ -6453,7 +6470,7 @@ list_subpartitioning_clause: ; hash_subpartitioning_clause: - SUBPARTITION BY IDENT '(' column_item_list ')' + SUBPARTITION BY normal_ident '(' column_item_list ')' { #ifdef ENABLE_MULTIPLE_NODES const char* message = "Un-support feature"; @@ -7052,9 +7069,9 @@ TypedTableElement: | TableConstraint { $$ = $1; } ; -ColIdForTableElement: IDENT { $$ = $1; } - | unreserved_keyword_without_key { $$ = pstrdup($1); } - | col_name_keyword { $$ = pstrdup($1); } +ColIdForTableElement: IDENT { $$ = downcase_str($1, is_quoted()); } + | unreserved_keyword_without_key { $$ = downcase_str(pstrdup($1), is_quoted()); } + | col_name_keyword { $$ = downcase_str(pstrdup($1), is_quoted()); } ; columnDefForTableElement: ColIdForTableElement Typename KVType ColCmprsMode create_generic_options ColQualList @@ -7518,7 +7535,7 @@ ColConstraintElem: n->location = @1; $$ = (Node *)n; } - | REFERENCES qualified_name opt_column_list key_match key_actions + | REFERENCES dolphin_qualified_name opt_column_list key_match key_actions { #ifdef ENABLE_MULTIPLE_NODES const char* message = "REFERENCES constraint is not yet supported."; @@ -7540,7 +7557,7 @@ ColConstraintElem: n->initially_valid = true; $$ = (Node *)n; } - | REFERENCES qualified_name opt_column_list key_match key_actions ENABLE_P + | REFERENCES dolphin_qualified_name opt_column_list key_match key_actions ENABLE_P { const char* message = "REFERENCES constraint is not yet supported."; InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc); @@ -7610,7 +7627,7 @@ ConstraintAttr: TableLikeClause: - LIKE qualified_name TableLikeOptionList + LIKE dolphin_qualified_name TableLikeOptionList { TableLikeClause *n = makeNode(TableLikeClause); n->relation = $2; @@ -7628,7 +7645,7 @@ TableLikeClause: #endif $$ = (Node *)n; } - | LIKE qualified_name INCLUDING_ALL excluding_option_list + | LIKE dolphin_qualified_name INCLUDING_ALL excluding_option_list { TableLikeClause *n = makeNode(TableLikeClause); n->relation = $2; @@ -7841,7 +7858,7 @@ ConstraintElem: NULL, yyscanner); $$ = (Node *)n; } - | FOREIGN KEY '(' columnList ')' REFERENCES qualified_name + | FOREIGN KEY '(' columnList ')' REFERENCES dolphin_qualified_name opt_column_list key_match key_actions ConstraintAttributeSpec { #ifdef ENABLE_MULTIPLE_NODES @@ -7983,7 +8000,7 @@ key_action: | SET DEFAULT { $$ = FKCONSTR_ACTION_SETDEFAULT; } ; -OptInherit_without_empty: INHERITS '(' qualified_name_list ')' +OptInherit_without_empty: INHERITS '(' dolphin_qualified_name_list ')' { const char* message = "CREATE TABLE ... INHERITS is not yet supported."; InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc); @@ -8075,7 +8092,7 @@ OptDatanodeName: DATANODE name { $$ = $2; } * related to distribution on other commands and to allow extensibility for * new distributions. */ -OptDistributeType: IDENT { $$ = $1; } +OptDistributeType: normal_ident { $$ = $1; } ; OptDistributeByInternal: DISTRIBUTE BY OptDistributeType '(' name_list ')' @@ -8551,7 +8568,7 @@ CreateAsStmt: $4->skipData = !($6); $$ = (Node *) ctas; } - | CREATE OptTemp TABLE qualified_name SelectStmtWithoutWithClause opt_with_data + | CREATE OptTemp TABLE dolphin_qualified_name SelectStmtWithoutWithClause opt_with_data { CreateTableAsStmt *ctas = makeNode(CreateTableAsStmt); ctas->query = $5; @@ -8584,7 +8601,7 @@ CreateAsStmt: create_as_target: create_as_target_dolphin { $$ = $1; } - | qualified_name + | dolphin_qualified_name { $$ = makeNode(IntoClause); $$->rel = $1; @@ -8606,7 +8623,7 @@ create_as_target: ; create_as_target_dolphin: - qualified_name opt_column_list CreateAsOptionList + dolphin_qualified_name opt_column_list CreateAsOptionList { $$ = makeNode(IntoClause); $$->rel = $1; @@ -8629,7 +8646,7 @@ create_as_target_dolphin: } } } - | qualified_name '(' columnList ')' + | dolphin_qualified_name '(' columnList ')' { $$ = makeNode(IntoClause); $$->rel = $1; @@ -10092,7 +10109,7 @@ generic_option_arg: * CREATE SERVER name [TYPE] [VERSION] [OPTIONS] * *****************************************************************************/ -fdwName: IDENT {$$ = $1;}; +fdwName: normal_ident { $$ = $1;}; CreateForeignServerStmt: CREATE SERVER name opt_type opt_foreign_server_version FOREIGN DATA_P WRAPPER fdwName create_generic_options @@ -10195,7 +10212,7 @@ AlterForeignServerStmt: ALTER SERVER name foreign_server_version alter_generic_o *****************************************************************************/ CreateForeignTableStmt: - CREATE FOREIGN TABLE qualified_name + CREATE FOREIGN TABLE dolphin_qualified_name OptForeignTableElementList SERVER name create_generic_options ForeignTblWritable OptForeignTableLogError OptForeignTableLogRemote OptPerNodeRejectLimit OptDistributeBy @@ -10229,7 +10246,7 @@ CreateForeignTableStmt: $$ = (Node *) n; } - | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name + | CREATE FOREIGN TABLE IF_P NOT EXISTS dolphin_qualified_name OptForeignTableElementList SERVER name create_generic_options ForeignTblWritable OptForeignTableLogError OptForeignTableLogRemote OptPerNodeRejectLimit OptDistributeBy @@ -10264,7 +10281,7 @@ CreateForeignTableStmt: $$ = (Node *) n; } /* ENABLE_MOT BEGIN */ - | CREATE FOREIGN TABLE qualified_name + | CREATE FOREIGN TABLE dolphin_qualified_name OptForeignTableElementList create_generic_options ForeignTblWritable OptForeignTableLogError OptForeignTableLogRemote OptPerNodeRejectLimit OptDistributeBy @@ -10306,7 +10323,7 @@ CreateForeignTableStmt: $$ = (Node *) n; } - | CREATE FOREIGN TABLE IF_P NOT EXISTS qualified_name + | CREATE FOREIGN TABLE IF_P NOT EXISTS dolphin_qualified_name OptForeignTableElementList create_generic_options ForeignTblWritable OptForeignTableLogError OptForeignTableLogRemote OptPerNodeRejectLimit OptDistributeBy @@ -10415,7 +10432,7 @@ ForeignPosition: ; ForeignTableLikeClause: - LIKE qualified_name + LIKE dolphin_qualified_name { TableLikeClause *n = makeNode(TableLikeClause); n->relation = $2; @@ -10424,8 +10441,8 @@ ForeignTableLikeClause: ; OptForeignTableLogError: - LOG_P INTO qualified_name { $$ = (Node*)$3; } - | WITH qualified_name { $$ = (Node*)$2; } + LOG_P INTO dolphin_qualified_name { $$ = (Node*)$3; } + | WITH dolphin_qualified_name { $$ = (Node*)$2; } | /*EMPTY*/ { $$ = NULL;} ; @@ -10553,7 +10570,7 @@ CreateUserMappingStmt: CREATE USER MAPPING FOR auth_ident SERVER name create_gen auth_ident: CURRENT_USER { $$ = "current_user"; } | USER { $$ = "current_user"; } - | RoleId { $$ = (strcmp($1, "public") == 0) ? NULL : $1; } + | RoleId { $$ = (strcmp(downcase_str($1, false), "public") == 0) ? NULL : $1; } ; /***************************************************************************** @@ -10743,7 +10760,7 @@ DropModelStmt: *****************************************************************************/ CreateRlsPolicyStmt: - CREATE RowLevelSecurityPolicyName ON qualified_name RLSDefaultPermissive + CREATE RowLevelSecurityPolicyName ON dolphin_qualified_name RLSDefaultPermissive RLSDefaultForCmd RLSDefaultToRole RLSOptionalUsingExpr { @@ -10770,7 +10787,7 @@ CreateRlsPolicyStmt: ; AlterRlsPolicyStmt: - ALTER RowLevelSecurityPolicyName ON qualified_name RLSOptionalToRole + ALTER RowLevelSecurityPolicyName ON dolphin_qualified_name RLSOptionalToRole RLSOptionalUsingExpr { AlterRlsPolicyStmt *n = makeNode(AlterRlsPolicyStmt); @@ -10850,7 +10867,7 @@ row_level_security_role: ; RLSDefaultPermissive: - AS IDENT + AS normal_ident { if (strcmp($2, "permissive") == 0) $$ = true; @@ -11077,7 +11094,7 @@ DropDataSourceStmt: DROP DATA_P SOURCE_P name opt_drop_behavior CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON - qualified_name TriggerForSpec TriggerWhen + dolphin_qualified_name TriggerForSpec TriggerWhen EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')' { CreateTrigStmt *n = makeNode(CreateTrigStmt); @@ -11097,7 +11114,7 @@ CreateTrigStmt: $$ = (Node *)n; } | CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON - qualified_name OptConstrFromTable ConstraintAttributeSpec + dolphin_qualified_name OptConstrFromTable ConstraintAttributeSpec FOR EACH ROW TriggerWhen EXECUTE PROCEDURE func_name '(' TriggerFuncArgs ')' { @@ -11212,7 +11229,7 @@ TriggerFuncArg: ; OptConstrFromTable: - FROM qualified_name { $$ = $2; } + FROM dolphin_qualified_name { $$ = $2; } | /*EMPTY*/ { $$ = NULL; } ; @@ -11524,7 +11541,7 @@ def_elem: ColLabel '=' def_arg /* Note: any simple identifier will be returned as a type name! */ def_arg: func_type { $$ = (Node *)$1; } - | reserved_keyword { $$ = (Node *)makeString(pstrdup($1)); } + | reserved_keyword { $$ = (Node *)makeString(downcase_str(pstrdup($1), is_quoted())); } | qual_all_Op { $$ = (Node *)$1; } | NumericOnly { $$ = (Node *)$1; } | Sconst { $$ = (Node *)makeString($1); } @@ -11557,7 +11574,7 @@ old_aggr_list: old_aggr_elem { $$ = list_make1($1); } * the item names needed in old aggregate definitions are likely to become * SQL keywords. */ -old_aggr_elem: IDENT '=' def_arg +old_aggr_elem: normal_ident '=' def_arg { $$ = makeDefElem($1, (Node *)$3); } @@ -11928,6 +11945,31 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior opt_purge } $$ = (Node *)n; } + | DROP opt_temporary TABLE IF_P EXISTS dolphin_any_name_list opt_drop_behavior opt_purge + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_TABLE; + n->missing_ok = TRUE; + n->objects = $6; + n->arguments = NIL; + n->behavior = $7; + n->concurrent = false; + n->purge = $8; + + $$ = (Node *)n; + } + | DROP opt_temporary TABLE dolphin_any_name_list opt_drop_behavior opt_purge + { + DropStmt *n = makeNode(DropStmt); + n->removeType = OBJECT_TABLE; + n->missing_ok = FALSE; + n->objects = $4; + n->arguments = NIL; + n->behavior = $5; + n->concurrent = false; + n->purge = $6; + $$ = (Node *)n; + } | DROP INDEX IF_P EXISTS any_name_list opt_drop_behavior opt_purge on_table { DropStmt *n = makeNode(DropStmt); @@ -11994,7 +12036,7 @@ DropStmt: DROP drop_type IF_P EXISTS any_name_list opt_drop_behavior opt_purge ; on_table: - ON qualified_name { $$ = NULL; } + ON dolphin_qualified_name { $$ = NULL; } | /* EMPTY */ { $$ = NULL; } ; @@ -12008,8 +12050,7 @@ opt_temporary: | /* EMPTY */ { $$ = NULL; } ; -drop_type: opt_temporary TABLE { $$ = OBJECT_TABLE; } - | CONTVIEW { $$ = OBJECT_CONTQUERY; } +drop_type: CONTVIEW { $$ = OBJECT_CONTQUERY; } | STREAM { $$ = OBJECT_STREAM; } | SEQUENCE { $$ = OBJECT_SEQUENCE; } | LARGE_P SEQUENCE { $$ = OBJECT_LARGE_SEQUENCE; } @@ -12036,16 +12077,56 @@ any_name_list: | any_name_list ',' any_name { $$ = lappend($1, $3); } ; +dolphin_any_name_list: + dolphin_any_name { $$ = list_make1($1); } + | dolphin_any_name_list ',' dolphin_any_name { $$ = lappend($1, $3); } + ; + any_name: ColId { $$ = list_make1(makeString($1)); } | ColId attrs { $$ = lcons(makeString($1), $2); } ; +dolphin_any_name: DolphinColId { $$ = list_make1(makeString(GetDolphinObjName($1->str, $1->is_quoted))); } + | DolphinColId dolphin_attrs + { + List* list = $2; + List* result = list_make1(makeString(downcase_str($1->str, $1->is_quoted))); + ListCell * cell = NULL; + int length = list_length($2); + int count = 1; + foreach (cell, list) { + DolphinString* dolphinString = (DolphinString*)lfirst(cell); + Value* value = (Value*)(dolphinString->node); + char* str = strVal(value); + bool is_quoted = dolphinString->is_quoted; + if (length == 1 && count == 1) { + /* schema_name.table_name */ + result = lappend(result, makeString(GetDolphinObjName(str, is_quoted))); + } else if (count == 2) { + /* category_name.schema_name.table_name */ + result = lappend(result, makeString(GetDolphinObjName(str, is_quoted))); + } else { + /* other_names */ + result = lappend(result, makeString(downcase_str(str, is_quoted))); + } + count++; + } + $$ = result; + } + ; + attrs: '.' attr_name { $$ = list_make1(makeString($2)); } | attrs '.' attr_name { $$ = lappend($1, makeString($3)); } ; +dolphin_attrs: '.' DolphinColLabel + { $$ = list_make1($2); } + | dolphin_attrs '.' DolphinColLabel + { $$ = lappend($1, $3); } + ; + /***************************************************************************** * @@ -12105,6 +12186,15 @@ CommentStmt: n->comment = $6; $$ = (Node *) n; } + | COMMENT ON dolphin_comment_type dolphin_any_name IS comment_text + { + CommentStmt *n = makeNode(CommentStmt); + n->objtype = $3; + n->objname = $4; + n->objargs = NIL; + n->comment = $6; + $$ = (Node *) n; + } | COMMENT ON AGGREGATE func_name aggr_args IS comment_text { CommentStmt *n = makeNode(CommentStmt); @@ -12132,7 +12222,7 @@ CommentStmt: n->comment = $7; $$ = (Node *) n; } - | COMMENT ON CONSTRAINT name ON any_name IS comment_text + | COMMENT ON CONSTRAINT name ON dolphin_any_name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_CONSTRAINT; @@ -12160,7 +12250,7 @@ CommentStmt: n->comment = $6; $$ = (Node *) n; } - | COMMENT ON TRIGGER name ON any_name IS comment_text + | COMMENT ON TRIGGER name ON dolphin_any_name IS comment_text { CommentStmt *n = makeNode(CommentStmt); n->objtype = OBJECT_TRIGGER; @@ -12255,7 +12345,6 @@ comment_type: | INDEX { $$ = OBJECT_INDEX; } | SEQUENCE { $$ = OBJECT_SEQUENCE; } | LARGE_P SEQUENCE { $$ = OBJECT_LARGE_SEQUENCE; } - | TABLE { $$ = OBJECT_TABLE; } | DOMAIN_P { $$ = OBJECT_DOMAIN; } | TYPE_P { $$ = OBJECT_TYPE; } | VIEW { $$ = OBJECT_VIEW; } @@ -12265,13 +12354,17 @@ comment_type: | CONVERSION_P { $$ = OBJECT_CONVERSION; } | TABLESPACE { $$ = OBJECT_TABLESPACE; } | EXTENSION { $$ = OBJECT_EXTENSION; } - | ROLE { $$ = OBJECT_ROLE; } - | USER { $$ = OBJECT_USER; } - | FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; } | SERVER { $$ = OBJECT_FOREIGN_SERVER; } | FOREIGN DATA_P WRAPPER { $$ = OBJECT_FDW; } ; +dolphin_comment_type: + TABLE { $$ = OBJECT_TABLE; } + | FOREIGN TABLE { $$ = OBJECT_FOREIGN_TABLE; } + | ROLE { $$ = OBJECT_ROLE; } + | USER { $$ = OBJECT_USER; } + ; + comment_text: Sconst { $$ = $1; } | NULL_P { $$ = NULL; } @@ -12758,21 +12851,21 @@ privilege_list: privilege { $$ = list_make1($1); } privilege: SELECT opt_column_list { AccessPriv *n = makeNode(AccessPriv); - n->priv_name = pstrdup($1); + n->priv_name = downcase_str(pstrdup($1), false); n->cols = $2; $$ = n; } | REFERENCES opt_column_list { AccessPriv *n = makeNode(AccessPriv); - n->priv_name = pstrdup($1); + n->priv_name = downcase_str(pstrdup($1), false); n->cols = $2; $$ = n; } | CREATE opt_column_list { AccessPriv *n = makeNode(AccessPriv); - n->priv_name = pstrdup($1); + n->priv_name = downcase_str(pstrdup($1), false); n->cols = $2; $$ = n; } @@ -12800,7 +12893,7 @@ routine_privilege: ALTER ROUTINE { AccessPriv *n = makeNode(AccessPriv); - n->priv_name = pstrdup($1); + n->priv_name = downcase_str(pstrdup($1), false); n->cols = NULL; $$ = n; } @@ -12856,7 +12949,7 @@ temporary_privilege: CREATE TEMPORARY TABLES { AccessPriv *n = makeNode(AccessPriv); - n->priv_name = pstrdup($2); + n->priv_name = downcase_str(pstrdup($2), false); n->cols = NULL; $$ = n; } @@ -12886,7 +12979,7 @@ temporary_target: * opt_table. You're going to get conflicts. */ privilege_target: - qualified_name_list + dolphin_qualified_name_list { PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget)); n->targtype = ACL_TARGET_OBJECT; @@ -12894,7 +12987,7 @@ privilege_target: n->objs = $1; $$ = n; } - | TABLE qualified_name_list + | TABLE dolphin_qualified_name_list { PrivTarget *n = (PrivTarget *) palloc(sizeof(PrivTarget)); n->targtype = ACL_TARGET_OBJECT; @@ -13098,7 +13191,7 @@ grantee: RoleId { PrivGrantee *n = makeNode(PrivGrantee); /* This hack lets us avoid reserving PUBLIC as a keyword*/ - if (strcmp($1, "public") == 0) + if (strcmp(downcase_str($1, false), "public") == 0) n->rolname = NULL; else n->rolname = $1; @@ -13108,7 +13201,7 @@ grantee: RoleId { PrivGrantee *n = makeNode(PrivGrantee); /* Treat GROUP PUBLIC as a synonym for PUBLIC */ - if (strcmp($2, "public") == 0) + if (strcmp(downcase_str($2, false), "public") == 0) n->rolname = NULL; else n->rolname = $2; @@ -13770,21 +13863,21 @@ index_params: index_elem { $$ = list_make1($1); } ; index_method_relation_clause: - ON qualified_name USING access_method + ON dolphin_qualified_name USING access_method { IndexMethodRelationClause* result = (IndexMethodRelationClause*)palloc0(sizeof(IndexMethodRelationClause)); result->relation = $2; result->accessMethod = $4; $$ = result; } - | ON qualified_name + | ON dolphin_qualified_name { IndexMethodRelationClause* result = (IndexMethodRelationClause*)palloc0(sizeof(IndexMethodRelationClause)); result->relation = $2; result->accessMethod = NULL; $$ = result; } - | USING access_method ON qualified_name + | USING access_method ON dolphin_qualified_name { IndexMethodRelationClause* result = (IndexMethodRelationClause*)palloc0(sizeof(IndexMethodRelationClause)); result->relation = $4; @@ -15513,7 +15606,7 @@ OptimizeStmt: *****************************************************************************/ ReindexStmt: - REINDEX reindex_type qualified_name opt_force + REINDEX reindex_type dolphin_qualified_name opt_force { ReindexStmt *n = makeNode(ReindexStmt); n->kind = $2; @@ -15522,12 +15615,10 @@ ReindexStmt: $$ = (Node *)n; } | - REINDEX reindex_type qualified_name PARTITION ColId opt_force + REINDEX reindex_type dolphin_qualified_name PARTITION ColId opt_force { ReindexStmt *n = makeNode(ReindexStmt); - if ($2 == OBJECT_INDEX) - n->kind = OBJECT_INDEX_PARTITION; - else if($2 == OBJECT_TABLE) + if($2 == OBJECT_TABLE) n->kind = OBJECT_TABLE_PARTITION; else n->kind = OBJECT_INTERNAL_PARTITION; @@ -15535,6 +15626,22 @@ ReindexStmt: n->name = $5; $$ = (Node *)n; } + | REINDEX INDEX qualified_name opt_force + { + ReindexStmt *n = makeNode(ReindexStmt); + n->kind = OBJECT_INDEX; + n->relation = $3; + n->name = NULL; + $$ = (Node *)n; + } + | REINDEX INDEX qualified_name PARTITION ColId opt_force + { + ReindexStmt *n = makeNode(ReindexStmt); + n->kind = OBJECT_INDEX_PARTITION; + n->relation = $3; + n->name = $5; + $$ = (Node *)n; + } | REINDEX SYSTEM_P name opt_force { ReindexStmt *n = makeNode(ReindexStmt); @@ -15558,8 +15665,7 @@ ReindexStmt: ; reindex_type: - INDEX { $$ = OBJECT_INDEX; } - | TABLE { $$ = OBJECT_TABLE; } + TABLE { $$ = OBJECT_TABLE; } | INTERNAL TABLE { $$ = OBJECT_INTERNAL; } ; @@ -15730,7 +15836,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name $$ = (Node *)n; } /* Rename Row Level Security Policy */ - | ALTER RowLevelSecurityPolicyName ON qualified_name RENAME TO name + | ALTER RowLevelSecurityPolicyName ON dolphin_qualified_name RENAME TO name { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_RLSPOLICY; @@ -15780,13 +15886,13 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name n->missing_ok = true; $$ = (Node *)n; } - | ALTER TABLE relation_expr RENAME to_or_as name + | ALTER TABLE relation_expr RENAME to_or_as DolphinColId { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_TABLE; n->relation = $3; n->subname = NULL; - n->newname = $6; + n->newname = $6->str; n->missing_ok = false; $$ = (Node *)n; } @@ -16076,7 +16182,6 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name n->missing_ok = true; $$ = (Node *)n; } - | ALTER TABLE relation_expr FORCE { VacuumStmt *n = makeNode(VacuumStmt); @@ -16107,7 +16212,7 @@ RenameStmt: ALTER AGGREGATE func_name aggr_args RENAME TO name n->missing_ok = true; $$ = (Node *)n; } - | ALTER TRIGGER name ON qualified_name RENAME TO name + | ALTER TRIGGER name ON dolphin_qualified_name RENAME TO name { RenameStmt *n = makeNode(RenameStmt); n->renameType = OBJECT_TRIGGER; @@ -17568,7 +17673,7 @@ load_col_data_type: ; load_col_sql_str: - IDENT + normal_ident { $$ = makeStringConst($1, @1); } @@ -17633,7 +17738,7 @@ load_when_option_item: 3. "string" */ load_quote_str: - IDENT { $$ = $1; } + normal_ident { $$ = $1; } | Sconst { $$ = $1; } /***************************************************************************** @@ -18065,7 +18170,7 @@ CreateConversionStmt: *****************************************************************************/ ClusterStmt: - CLUSTER opt_verbose qualified_name cluster_index_specification + CLUSTER opt_verbose dolphin_qualified_name cluster_index_specification { ClusterStmt *n = makeNode(ClusterStmt); $3->partitionname = NULL; @@ -18074,7 +18179,7 @@ ClusterStmt: n->verbose = $2; $$ = (Node*)n; } - | CLUSTER opt_verbose qualified_name PARTITION '(' name ')' cluster_index_specification + | CLUSTER opt_verbose dolphin_qualified_name PARTITION '(' name ')' cluster_index_specification { ClusterStmt *n = makeNode(ClusterStmt); $3->partitionname = $6; @@ -18091,8 +18196,8 @@ ClusterStmt: n->verbose = $2; $$ = (Node*)n; } - /* kept for pre-8.3 compatibility */ - | CLUSTER opt_verbose index_name ON qualified_name + /* kept for pre-8.3 compatibility, dolphin_index_name used to deal with the conflict*/ + | CLUSTER opt_verbose dolphin_index_name ON dolphin_qualified_name { ClusterStmt *n = makeNode(ClusterStmt); n->relation = $5; @@ -18124,7 +18229,7 @@ VacuumStmt: n->options |= VACOPT_MERGE; $$ = (Node *)n; } - | VACUUM opt_deltamerge qualified_name + | VACUUM opt_deltamerge dolphin_qualified_name { VacuumStmt *n = makeNode(VacuumStmt); if ($2) @@ -18142,7 +18247,7 @@ VacuumStmt: } $$ = (Node *)n; } - | VACUUM opt_hdfsdirectory qualified_name + | VACUUM opt_hdfsdirectory dolphin_qualified_name { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VACUUM; @@ -18188,7 +18293,7 @@ VacuumStmt: n->va_cols = NIL; $$ = (Node *)n; } - | VACUUM opt_full opt_freeze opt_verbose opt_compact qualified_name + | VACUUM opt_full opt_freeze opt_verbose opt_compact dolphin_qualified_name { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VACUUM; @@ -18223,7 +18328,7 @@ VacuumStmt: n->va_cols = NIL; $$ = (Node *)n; } - | VACUUM opt_full opt_freeze opt_verbose opt_compact qualified_name PARTITION '('name')' + | VACUUM opt_full opt_freeze opt_verbose opt_compact dolphin_qualified_name PARTITION '('name')' { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VACUUM; @@ -18245,7 +18350,7 @@ VacuumStmt: $6->partitionname = $9; $$ = (Node *)n; } - | VACUUM opt_full opt_freeze opt_verbose opt_compact qualified_name SUBPARTITION '('name')' + | VACUUM opt_full opt_freeze opt_verbose opt_compact dolphin_qualified_name SUBPARTITION '('name')' { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VACUUM; @@ -18298,7 +18403,7 @@ VacuumStmt: n->va_cols = NIL; $$ = (Node *) n; } - | VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list + | VACUUM '(' vacuum_option_list ')' dolphin_qualified_name opt_name_list { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VACUUM | $3; @@ -18312,7 +18417,7 @@ VacuumStmt: n->options |= VACOPT_ANALYZE; $$ = (Node *) n; } - | VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list PARTITION '('name')' + | VACUUM '(' vacuum_option_list ')' dolphin_qualified_name opt_name_list PARTITION '('name')' { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VACUUM | $3; @@ -18327,7 +18432,7 @@ VacuumStmt: $5->partitionname = $9; $$ = (Node *) n; } - | VACUUM '(' vacuum_option_list ')' qualified_name opt_name_list SUBPARTITION '('name')' + | VACUUM '(' vacuum_option_list ')' dolphin_qualified_name opt_name_list SUBPARTITION '('name')' { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VACUUM | $3; @@ -18369,7 +18474,7 @@ AnalyzeStmt: n->va_cols = NIL; $$ = (Node *)n; } - | analyze_keyword opt_verbose qualified_name opt_analyze_column_define + | analyze_keyword opt_verbose dolphin_qualified_name opt_analyze_column_define { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_ANALYZE; @@ -18381,7 +18486,7 @@ AnalyzeStmt: n->va_cols = $4; $$ = (Node *)n; } - | analyze_keyword opt_verbose qualified_name opt_name_list PARTITION '('name')' + | analyze_keyword opt_verbose dolphin_qualified_name opt_name_list PARTITION '('name')' { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_ANALYZE; @@ -18453,7 +18558,7 @@ VerifyStmt: } /* analyse verify fast|complete index_name/table_name*/ - | analyze_keyword opt_verify opt_verify_options qualified_name opt_cascade + | analyze_keyword opt_verify opt_verify_options dolphin_qualified_name opt_cascade { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VERIFY | $3; @@ -18466,7 +18571,7 @@ VerifyStmt: } /* analyse verify fast|complete table_name partition (partition_name) cascade*/ - | analyze_keyword opt_verify opt_verify_options qualified_name PARTITION '('name')' opt_cascade + | analyze_keyword opt_verify opt_verify_options dolphin_qualified_name PARTITION '('name')' opt_cascade { VacuumStmt *n = makeNode(VacuumStmt); n->options = VACOPT_VERIFY | $3; @@ -20069,7 +20174,7 @@ ExplainStmt: n->options = list_make1(makeDefElem("plan", NULL)); $$ = (Node *) n; } - | describe_command qualified_name + | describe_command dolphin_qualified_name { SelectStmt *n = makeDescribeQuery($2->schemaname, $2->relname); $$ = (Node *) n; @@ -20562,7 +20667,7 @@ into_empty: INTO * So AS is required for now. */ insert_target: - qualified_name insert_partition_clause + dolphin_qualified_name insert_partition_clause { if ($2 != NULL) { $1->partitionname = $2->partitionname; @@ -20573,7 +20678,7 @@ insert_target: } $$ = $1; } - | qualified_name insert_partition_clause AS ColId + | dolphin_qualified_name insert_partition_clause AS ColId { if ($2 != NULL) { $1->partitionname = $2->partitionname; @@ -20940,11 +21045,11 @@ multiple_set_clause: ; set_target: - ColId opt_indirection + DolphinColId opt_dolphin_indirection { $$ = makeNode(ResTarget); - $$->name = $1; - $$->indirection = check_indirection($2, yyscanner); + $$->name = $1->str; + $$->indirection = check_indirection(GetNameListFromDolphinString($2), yyscanner); $$->val = NULL; /* upper production sets this */ $$->location = @1; } @@ -21455,27 +21560,27 @@ into_clause: * since TEMP is not a reserved word. See also OptTemp. */ OptTempTableName: - TEMPORARY opt_table qualified_name + TEMPORARY opt_table dolphin_qualified_name { $$ = $3; $$->relpersistence = RELPERSISTENCE_TEMP; } - | TEMP opt_table qualified_name + | TEMP opt_table dolphin_qualified_name { $$ = $3; $$->relpersistence = RELPERSISTENCE_TEMP; } - | LOCAL TEMPORARY opt_table qualified_name + | LOCAL TEMPORARY opt_table dolphin_qualified_name { $$ = $4; $$->relpersistence = RELPERSISTENCE_TEMP; } - | LOCAL TEMP opt_table qualified_name + | LOCAL TEMP opt_table dolphin_qualified_name { $$ = $4; $$->relpersistence = RELPERSISTENCE_TEMP; } - | GLOBAL TEMPORARY opt_table qualified_name + | GLOBAL TEMPORARY opt_table dolphin_qualified_name { $$ = $4; #ifdef ENABLE_MULTIPLE_NODES @@ -21489,7 +21594,7 @@ OptTempTableName: $$->relpersistence = RELPERSISTENCE_GLOBAL_TEMP; #endif } - | GLOBAL TEMP opt_table qualified_name + | GLOBAL TEMP opt_table dolphin_qualified_name { $$ = $4; #ifdef ENABLE_MULTIPLE_NODES @@ -21503,17 +21608,17 @@ OptTempTableName: $$->relpersistence = RELPERSISTENCE_GLOBAL_TEMP; #endif } - | UNLOGGED opt_table qualified_name + | UNLOGGED opt_table dolphin_qualified_name { $$ = $3; $$->relpersistence = RELPERSISTENCE_UNLOGGED; } - | TABLE qualified_name + | TABLE dolphin_qualified_name { $$ = $2; $$->relpersistence = RELPERSISTENCE_PERMANENT; } - | qualified_name + | dolphin_qualified_name { $$ = $1; $$->relpersistence = RELPERSISTENCE_PERMANENT; @@ -21921,7 +22026,7 @@ for_locking_strength: ; locked_rels_list: - OF qualified_name_list { $$ = $2; } + OF dolphin_qualified_name_list { $$ = $2; } | /* EMPTY */ { $$ = NIL; } ; @@ -22005,12 +22110,12 @@ table_ref: relation_expr #endif $$ = (Node *) $1; } - | relation_expr alias_clause + | relation_expr dolphin_alias_clause { $1->alias = $2; $$ = (Node *) $1; } - | relation_expr opt_alias_clause tablesample_clause + | relation_expr opt_dolphin_alias_clause tablesample_clause { RangeTableSample *n = (RangeTableSample *) $3; $1->alias = $2; @@ -22018,7 +22123,7 @@ table_ref: relation_expr n->relation = (Node *) $1; $$ = (Node *) n; } - | relation_expr opt_alias_clause timecapsule_clause + | relation_expr opt_dolphin_alias_clause timecapsule_clause { RangeTimeCapsule *n = (RangeTimeCapsule *) $3; $1->alias = $2; @@ -22062,28 +22167,28 @@ table_ref: relation_expr $1->issubpartition = true; $$ = (Node *)$1; } - | relation_expr PARTITION '(' name ')' alias_clause + | relation_expr PARTITION '(' name ')' dolphin_alias_clause { $1->partitionname = $4; $1->alias = $6; $1->ispartition = true; $$ = (Node *)$1; } - | relation_expr SUBPARTITION '(' name ')' alias_clause + | relation_expr SUBPARTITION '(' name ')' dolphin_alias_clause { $1->subpartitionname = $4; $1->alias = $6; $1->issubpartition = true; $$ = (Node *)$1; } - | relation_expr PARTITION_FOR '(' expr_list ')' alias_clause + | relation_expr PARTITION_FOR '(' expr_list ')' dolphin_alias_clause { $1->partitionKeyValuesList = $4; $1->alias = $6; $1->ispartition = true; $$ = (Node *)$1; } - | relation_expr SUBPARTITION_FOR '(' expr_list ')' alias_clause + | relation_expr SUBPARTITION_FOR '(' expr_list ')' dolphin_alias_clause { $1->partitionKeyValuesList = $4; $1->alias = $6; @@ -22184,7 +22289,7 @@ table_ref: relation_expr { $$ = (Node *) $1; } - | '(' joined_table ')' alias_clause + | '(' joined_table ')' dolphin_alias_clause { $2->alias = $4; $$ = (Node *) $2; @@ -22367,10 +22472,39 @@ alias_clause: } ; +dolphin_alias_clause: + AS DolphinColId '(' name_list ')' + { + $$ = makeNode(Alias); + $$->aliasname = GetDolphinObjName($2->str, $2->is_quoted); + $$->colnames = $4; + } + | AS DolphinColId + { + $$ = makeNode(Alias); + $$->aliasname = GetDolphinObjName($2->str, $2->is_quoted); + } + | DolphinColId '(' name_list ')' + { + $$ = makeNode(Alias); + $$->aliasname = GetDolphinObjName($1->str, $1->is_quoted); + $$->colnames = $3; + } + | DolphinColId + { + $$ = makeNode(Alias); + $$->aliasname = GetDolphinObjName($1->str, $1->is_quoted); + } + ; + opt_alias_clause: alias_clause { $$ = $1; } | /*EMPTY*/ { $$ = NULL; } ; +opt_dolphin_alias_clause: dolphin_alias_clause { $$ = $1; } + | /*EMPTY*/ { $$ = NULL; } + ; + join_type: FULL join_outer { $$ = JOIN_FULL; } | LEFT join_outer { $$ = JOIN_LEFT; } | RIGHT join_outer { $$ = JOIN_RIGHT; } @@ -22396,7 +22530,7 @@ join_qual: USING '(' name_list ')' { $$ = (Node *) $3; } relation_expr: - qualified_name OptSnapshotVersion + dolphin_qualified_name OptSnapshotVersion { /* default inheritance */ $$ = $1; @@ -22409,21 +22543,21 @@ relation_expr: $$->inhOpt = INH_DEFAULT; $$->alias = NULL; } - | qualified_name '*' + | dolphin_qualified_name '*' { /* inheritance query */ $$ = $1; $$->inhOpt = INH_YES; $$->alias = NULL; } - | ONLY qualified_name + | ONLY dolphin_qualified_name { /* no inheritance */ $$ = $2; $$->inhOpt = INH_NO; $$->alias = NULL; } - | ONLY '(' qualified_name ')' + | ONLY '(' dolphin_qualified_name ')' { /* no inheritance, SQL99-style syntax */ $$ = $3; @@ -22452,17 +22586,17 @@ relation_expr_opt_alias: relation_expr %prec UMINUS { $$ = $1; } - | relation_expr ColId + | relation_expr DolphinColId { Alias *alias = makeNode(Alias); - alias->aliasname = $2; + alias->aliasname = $2->str; $1->alias = alias; $$ = $1; } - | relation_expr AS ColId + | relation_expr AS DolphinColId { Alias *alias = makeNode(Alias); - alias->aliasname = $3; + alias->aliasname = $3->str; $1->alias = alias; $$ = $1; } @@ -22477,7 +22611,7 @@ relation_expr_opt_alias: relation_expr %prec UMINUS } $$ = $1; } - | relation_expr update_delete_partition_clause ColId + | relation_expr update_delete_partition_clause DolphinColId { if ($2 != NULL) { $1->partitionname = $2->partitionname; @@ -22487,11 +22621,11 @@ relation_expr_opt_alias: relation_expr %prec UMINUS $1->issubpartition = $2->issubpartition; } Alias *alias = makeNode(Alias); - alias->aliasname = $3; + alias->aliasname = $3->str; $1->alias = alias; $$ = $1; } - | relation_expr update_delete_partition_clause AS ColId + | relation_expr update_delete_partition_clause AS DolphinColId { if ($2 != NULL) { $1->partitionname = $2->partitionname; @@ -22501,7 +22635,7 @@ relation_expr_opt_alias: relation_expr %prec UMINUS $1->issubpartition = $2->issubpartition; } Alias *alias = makeNode(Alias); - alias->aliasname = $4; + alias->aliasname = $4->str; $1->alias = alias; $$ = $1; } @@ -24482,7 +24616,7 @@ func_expr: func_application within_group_clause over_clause { $$ = $1; } ; -func_application: func_name '(' ')' +func_application: dolphin_func_name '(' ')' { FuncCall *n = makeNode(FuncCall); n->funcname = $1; @@ -24496,7 +24630,7 @@ func_application: func_name '(' ')' n->call_func = false; $$ = (Node *)n; } - | func_name '(' func_arg_list opt_sort_clause ')' + | dolphin_func_name '(' func_arg_list opt_sort_clause ')' { FuncCall *n = makeNode(FuncCall); n->funcname = $1; @@ -24510,7 +24644,7 @@ func_application: func_name '(' ')' n->call_func = false; $$ = (Node *)n; } - | func_name '(' VARIADIC func_arg_expr opt_sort_clause ')' + | dolphin_func_name '(' VARIADIC func_arg_expr opt_sort_clause ')' { FuncCall *n = makeNode(FuncCall); n->funcname = $1; @@ -24524,7 +24658,7 @@ func_application: func_name '(' ')' n->call_func = false; $$ = (Node *)n; } - | func_name '(' func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause ')' + | dolphin_func_name '(' func_arg_list ',' VARIADIC func_arg_expr opt_sort_clause ')' { FuncCall *n = makeNode(FuncCall); n->funcname = $1; @@ -24538,7 +24672,7 @@ func_application: func_name '(' ')' n->call_func = false; $$ = (Node *)n; } - | func_name '(' ALL func_arg_list opt_sort_clause ')' + | dolphin_func_name '(' ALL func_arg_list opt_sort_clause ')' { FuncCall *n = makeNode(FuncCall); n->funcname = $1; @@ -24556,7 +24690,7 @@ func_application: func_name '(' ')' n->call_func = false; $$ = (Node *)n; } - | func_name '(' DISTINCT func_arg_list opt_sort_clause ')' + | dolphin_func_name '(' DISTINCT func_arg_list opt_sort_clause ')' { FuncCall *n = makeNode(FuncCall); n->funcname = $1; @@ -24570,7 +24704,7 @@ func_application: func_name '(' ')' n->call_func = false; $$ = (Node *)n; } - | func_name '(' '*' ')' + | dolphin_func_name '(' '*' ')' { /* * We consider AGGREGATE(*) to invoke a parameterless @@ -26049,7 +26183,7 @@ extract_list: * - thomas 2001-04-12 */ extract_arg: - IDENT { $$ = $1; } + normal_ident { $$ = $1; } | YEAR_P { $$ = "year"; } | MONTH_P { $$ = "month"; } | DAY_P { $$ = "day"; } @@ -26070,7 +26204,7 @@ timestamp_arg_list: ; timestamp_units: - IDENT { $$ = $1; } + normal_ident { $$ = $1; } | YEAR_P { $$ = "year"; } | MONTH_P { $$ = "month"; } | DAY_P { $$ = "day"; } @@ -26291,13 +26425,62 @@ case_arg: a_expr { $$ = $1; } | /*EMPTY*/ { $$ = NULL; } ; -columnref: ColId +columnref: DolphinColId { - $$ = makeColumnRef($1, NIL, @1, yyscanner); + $$ = makeColumnRef(downcase_str($1->str, $1->is_quoted), NIL, @1, yyscanner); } - | ColId indirection + | DolphinColId dolphin_indirection { - $$ = makeColumnRef($1, $2, @1, yyscanner); + List* result = NIL; + ListCell* cell = NULL; + char* first_word = NULL; + int table_index = -1; + int count = 0; + int indices = 0; + foreach (cell, $2) { + DolphinString* dolphinString = (DolphinString*)lfirst(cell); + if (IsA(dolphinString->node, A_Indices)) { + indices++; + } + } + cell = NULL; + switch (list_length($2) - indices) + { + case 0: + /* column */ + first_word = downcase_str($1->str, $1->is_quoted); + break; + case 1: + /* table.column */ + first_word = GetDolphinObjName($1->str, $1->is_quoted); + break; + case 2: + /* schema.table.column */ + first_word = downcase_str($1->str, $1->is_quoted); + table_index = 0; + break; + default: + /* catalog.schema.table.column. ... */ + first_word = downcase_str($1->str, $1->is_quoted); + table_index = 1; + break; + } + foreach (cell, $2) { + DolphinString* dolphinString = (DolphinString*)lfirst(cell); + if (IsA(dolphinString->node, String)) { + Value* value = (Value*)(dolphinString->node); + char* text = strVal(value); + bool is_quoted = dolphinString->is_quoted; + if (count != table_index || (count == table_index && + GetSessionContext()->lower_case_table_names > 0)) { + text = downcase_str(text, is_quoted); + } + result = lappend(result, (Node*)makeString(text)); + } else { + result = lappend(result, dolphinString->node); + } + } + $$ = makeColumnRef(first_word, result, @1, yyscanner); } | EXCLUDED indirection { @@ -26346,11 +26529,57 @@ indirection: | indirection indirection_el { $$ = lappend($1, $2); } ; +dolphin_indirection: + dolphin_indirection_el { $$ = list_make1($1); } + | dolphin_indirection dolphin_indirection_el { $$ = lappend($1, $2); } + ; + +dolphin_indirection_el: + '.' DolphinColLabel + { + $$ = $2; + } + | ORA_JOINOP + { + $$ = makeDolphinStringByNode((Node *) makeString("(+)"), false); + } + | '.' '*' + { + $$ = makeDolphinStringByNode((Node *) makeNode(A_Star), false); + } + | '[' a_expr ']' + { + A_Indices *ai = makeNode(A_Indices); + ai->lidx = NULL; + ai->uidx = $2; + $$ = makeDolphinStringByNode((Node *) ai, false); + } + | '[' a_expr ':' a_expr ']' + { + A_Indices *ai = makeNode(A_Indices); + ai->lidx = $2; + ai->uidx = $4; + $$ = makeDolphinStringByNode((Node *) ai, false); + } + | '[' a_expr ',' a_expr ']' + { + A_Indices *ai = makeNode(A_Indices); + ai->lidx = $2; + ai->uidx = $4; + $$ = makeDolphinStringByNode((Node *) ai, false); + } + ; + opt_indirection: /*EMPTY*/ { $$ = NIL; } | opt_indirection indirection_el { $$ = lappend($1, $2); } ; +opt_dolphin_indirection: + /*EMPTY*/ { $$ = NIL; } + | opt_dolphin_indirection dolphin_indirection_el { $$ = lappend($1, $2); } + ; + opt_asymmetric: ASYMMETRIC | /*EMPTY*/ ; @@ -26413,7 +26642,7 @@ target_el: a_expr AS ColLabel * as an infix expression, which we accomplish by assigning * IDENT a precedence higher than POSTFIXOP. */ - | a_expr IDENT + | a_expr normal_ident { $$ = makeNode(ResTarget); $$->name = $2; @@ -26487,18 +26716,18 @@ target_el: a_expr AS ColLabel } ; -connect_by_root_expr: a_expr IDENT '.' IDENT +connect_by_root_expr: a_expr normal_ident '.' normal_ident { ValidateTripleTuple((Node*)$1, yyscanner, @2, $2); Node* cr = (Node*) makeColumnRef($2, list_make1(makeString($4)), @1, yyscanner); Node* n = MakeConnectByRootNode((ColumnRef*) cr, @1); $$ = makeNode(ResTarget); $$->name = MakeConnectByRootColName($2, $4); - $$->val = (Node*) n; + $$->val = (Node*) n; $$->indirection = NIL; $$->location = @1; } - | a_expr IDENT '.' IDENT as_empty IDENT + | a_expr normal_ident '.' normal_ident as_empty normal_ident { ValidateTripleTuple((Node*)$1, yyscanner, @2, $2); Node* cr = (Node*) makeColumnRef($2, list_make1(makeString($4)), @1, yyscanner); @@ -26509,7 +26738,7 @@ connect_by_root_expr: a_expr IDENT '.' IDENT $$->indirection = NIL; $$->location = @1; } - | a_expr IDENT as_empty IDENT + | a_expr normal_ident as_empty normal_ident { ValidateTripleTuple((Node*) $1, yyscanner, @2, $2); Node* cr = (Node*) makeColumnRef($2, NIL, @1, yyscanner); @@ -26533,6 +26762,11 @@ qualified_name_list: | qualified_name_list ',' qualified_name { $$ = lappend($1, $3); } ; +dolphin_qualified_name_list: + dolphin_qualified_name { $$ = list_make1($1); } + | dolphin_qualified_name_list ',' dolphin_qualified_name { $$ = lappend($1, $3); } + ; + /* * The production for a qualified relation name has to exactly match the * production for a qualified func_name, because in a FROM clause we cannot @@ -26574,12 +26808,57 @@ qualified_name: } ; +dolphin_qualified_name: + DolphinColId + { + $$ = makeRangeVar(NULL, GetDolphinObjName($1->str, $1->is_quoted), @1); + } + | DolphinColId dolphin_indirection + { + check_dolphin_qualified_name($2, yyscanner); + $$ = makeRangeVar(NULL, NULL, @1); + const char* message = "improper qualified name (too many dotted names)"; + DolphinString* first = NULL; + DolphinString* second = NULL; + switch (list_length($2)) + { + case 1: + $$->catalogname = NULL; + $$->schemaname = downcase_str($1->str, $1->is_quoted); + first = (DolphinString*)linitial($2); + $$->relname = strVal(first->node); + break; + case 2: + $$->catalogname = downcase_str($1->str, $1->is_quoted); + first = (DolphinString*)linitial($2); + second = (DolphinString*)lsecond($2); + $$->schemaname = downcase_str(strVal(first->node), first->is_quoted); + $$->relname = strVal(second->node); + break; + default: + InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc); + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("improper qualified name (too many dotted names): %s", + NameListToString(lcons(makeString($1->str), GetNameListFromDolphinString($2)))), + parser_errposition(@1))); + break; + } + } + ; + name_list: name { $$ = list_make1(makeString($1)); } | name_list ',' name { $$ = lappend($1, makeString($3)); } ; +dolphin_name_list: RoleId + { $$ = list_make1(makeString($1)); } + | dolphin_name_list ',' RoleId + { $$ = lappend($1, makeString($3)); } + ; + name: ColId { $$ = $1; }; @@ -26593,6 +26872,8 @@ attr_name: ColLabel { $$ = $1; }; index_name: ColId { $$ = $1; }; +dolphin_index_name: DolphinColId { $$ = downcase_str($1->str, $1->is_quoted); }; + file_name: Sconst { $$ = $1; }; /* @@ -26612,6 +26893,15 @@ func_name: type_function_name } ; +dolphin_func_name: type_function_name + { $$ = list_make1(makeString($1)); } + | DolphinColId dolphin_indirection + { + $$ = check_func_name(lcons(makeString(downcase_str($1->str, $1->is_quoted)), + GetNameListFromDolphinString($2)), yyscanner); + } + ; + func_name_opt_arg: func_name /* This rule is never used. */ @@ -26647,14 +26937,14 @@ AexprConst: Iconst */ $$ = makeBitStringConst($1, @1); } - | func_name Sconst + | dolphin_func_name Sconst { /* generic type 'literal' syntax */ TypeName *t = makeTypeNameFromNameList($1); t->location = @1; $$ = makeStringConstCast($2, @2, t); } - | func_name '(' func_arg_list opt_sort_clause ')' Sconst + | dolphin_func_name '(' func_arg_list opt_sort_clause ')' Sconst { /* generic syntax with a type modifier */ TypeName *t = makeTypeNameFromNameList($1); @@ -26751,7 +27041,11 @@ AexprConst: Iconst Iconst: ICONST { $$ = $1; }; Sconst: SCONST { $$ = $1; }; -RoleId: ColId { $$ = $1; }; + +RoleId: IDENT { $$ = GetDolphinObjName($1, is_quoted()); } + | unreserved_keyword { $$ = GetDolphinObjName(pstrdup($1), is_quoted()); } + | col_name_keyword { $$ = GetDolphinObjName(pstrdup($1), is_quoted()); } + ; SignedIconst: Iconst { $$ = $1; } | '+' Iconst { $$ = + $2; } @@ -26771,29 +27065,34 @@ SignedIconst: Iconst { $$ = $1; } /* Column identifier --- names that can be column, table, etc names. */ -ColId: IDENT { $$ = $1; } - | unreserved_keyword { $$ = pstrdup($1); } - | col_name_keyword { $$ = pstrdup($1); } +ColId: IDENT { $$ = downcase_str($1, is_quoted()); } + | unreserved_keyword { $$ = downcase_str(pstrdup($1), is_quoted()); } + | col_name_keyword { $$ = downcase_str(pstrdup($1), is_quoted()); } + ; + +DolphinColId: IDENT { $$ = makeDolphinStringByChar($1, is_quoted()); } + | unreserved_keyword { $$ = makeDolphinStringByChar(pstrdup($1), is_quoted()); } + | col_name_keyword { $$ = makeDolphinStringByChar(pstrdup($1), is_quoted()); } ; /* Type/function identifier --- names that can be type or function names. */ -type_function_name: IDENT { $$ = $1; } - | unreserved_keyword { $$ = pstrdup($1); } - | type_func_name_keyword { $$ = pstrdup($1); } +type_function_name: IDENT { $$ = downcase_str($1, is_quoted()); } + | unreserved_keyword { $$ = downcase_str(pstrdup($1), is_quoted()); } + | type_func_name_keyword { $$ = downcase_str(pstrdup($1), is_quoted()); } ; /* Column label --- allowed labels in "AS" clauses. * This presently includes *all* Postgres keywords. */ -ColLabel: IDENT { $$ = $1; } - | unreserved_keyword { $$ = pstrdup($1); } - | col_name_keyword { $$ = pstrdup($1); } - | type_func_name_keyword { $$ = pstrdup($1); } +ColLabel: IDENT { $$ = downcase_str($1, is_quoted()); } + | unreserved_keyword { $$ = downcase_str(pstrdup($1), is_quoted()); } + | col_name_keyword { $$ = downcase_str(pstrdup($1), is_quoted()); } + | type_func_name_keyword { $$ = downcase_str(pstrdup($1), is_quoted()); } | reserved_keyword { /* ROWNUM can not be used as alias */ - if (strcmp($1, "rownum") == 0) { + if (strcmp(downcase_str($1, is_quoted()), "rownum") == 0) { const char* message = "ROWNUM cannot be used as an alias"; InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc); ereport(errstate, @@ -26805,6 +27104,28 @@ ColLabel: IDENT { $$ = $1; } } ; +/* + * Column lable of dolphin type + */ +DolphinColLabel: IDENT { $$ = makeDolphinStringByChar($1, is_quoted()); } + | unreserved_keyword { $$ = makeDolphinStringByChar(pstrdup($1), is_quoted()); } + | col_name_keyword { $$ = makeDolphinStringByChar(pstrdup($1), is_quoted()); } + | type_func_name_keyword { $$ = makeDolphinStringByChar(pstrdup($1), is_quoted()); } + | reserved_keyword + { + /* ROWNUM can not be used as alias */ + if (strcmp($1, "rownum") == 0) { + const char* message = "ROWNUM cannot be used as an alias"; + InsertErrorMessage(message, u_sess->plsql_cxt.plpgsql_yylloc); + ereport(errstate, + (errcode(ERRCODE_SYNTAX_ERROR), + errmsg("ROWNUM cannot be used as an alias"), + parser_errposition(@1))); + } + $$ = makeDolphinStringByChar(pstrdup($1), is_quoted()); + } + ; + /* * Keyword category lists. Generally, every keyword present in @@ -27536,6 +27857,9 @@ reserved_keyword: | WITH ; +/* normal_ident */ +normal_ident: IDENT { $$ = downcase_str($1, is_quoted()); }; + %% /* @@ -27780,6 +28104,18 @@ check_qualified_name(List *names, core_yyscan_t yyscanner) } } +static void check_dolphin_qualified_name(List *names, core_yyscan_t yyscanner) +{ + ListCell *i; + + foreach(i, names) + { + DolphinString* elem = (DolphinString*)lfirst(i); + if (!IsA(elem->node, String)) + parser_yyerror("syntax error"); + } +} + /* check_func_name --- check the result of func_name production * * It's easiest to let the grammar production for func_name allow subscripts @@ -29872,6 +30208,45 @@ static Node* makeAnalyzeTableList(List *rangeVars) return makeStringConst(res.data, -1); } +static char* downcase_str(const char* ident, bool is_quoted) +{ + if (ident == NULL || is_quoted) { + return (char*)ident; + } + return downcase_truncate_identifier(ident, strlen((char*)ident), false); +} + +static DolphinString* makeDolphinString(char* str, Node* node, bool is_quoted) +{ + DolphinString* result = (DolphinString*)palloc(sizeof(DolphinString)); + result->str = str; + result->node = node; + result->is_quoted = is_quoted; + return result; +} + +static DolphinString* makeDolphinStringByChar(char* str, bool is_quoted) +{ + return makeDolphinString(str, (Node*)makeString(str), is_quoted); +} + +static DolphinString* makeDolphinStringByNode(Node* node, bool is_quoted) +{ + return makeDolphinString(strVal((Value*)node), node, is_quoted); +} + + +static List* GetNameListFromDolphinString(List* dolphinStringList) +{ + List* result = NIL; + ListCell* cell = NULL; + foreach (cell, dolphinStringList) { + DolphinString* element = (DolphinString*)lfirst(cell); + result = lappend(result, element->node); + } + return result; +} + /* * Check numbers of elements in a_expr from WITH ROLLUP clause, which is declared in group_by_list. * If the input expr is valid, directly return. Otherwise raise ERROR. @@ -29891,6 +30266,11 @@ static void with_rollup_check_elems_count(Node* expr) } } +static inline char* GetDolphinObjName(const char* string, bool is_quoted) +{ + return (GetSessionContext()->lower_case_table_names == 0) ? (char*)string : downcase_str(string, is_quoted); +} + /* * Must undefine this stuff before including scan.c, since it has different * definitions for these macros. diff --git a/contrib/dolphin/plugin_parser/scan.l b/contrib/dolphin/plugin_parser/scan.l index 070efe558b87187ab241ba20726bd15626ed4bf8..2652c5a84f2430e336019420886089b90c18da60 100644 --- a/contrib/dolphin/plugin_parser/scan.l +++ b/contrib/dolphin/plugin_parser/scan.l @@ -110,7 +110,7 @@ static void dealSahrpComment(core_yyscan_t yyscanner); */ extern int core_yyget_column(yyscan_t yyscanner); extern void core_yyset_column(int column_no, yyscan_t yyscanner); - +static char* CopyIdentifier(const char* ident, int len, bool warn); %} %option reentrant @@ -1066,7 +1066,7 @@ other . if (keyword != NULL) { - yylval->keyword = keyword->name; + yylval->keyword = pstrdup(yytext); /* Find the CREATE PROCEDURE syntax and set dolqstart. */ if (keyword->value == CREATE) @@ -1106,6 +1106,7 @@ other . yyextra->is_hint_str = true; } + yyextra->ident_quoted = false; return keyword->value; } @@ -1122,7 +1123,7 @@ other . yyleng = nchars; } - ident = downcase_truncate_identifier(yytext, yyleng, yyextra->warnOnTruncateIdent); + ident = CopyIdentifier(yytext, yyleng, yyextra->warnOnTruncateIdent); yylval->str = ident; yyextra->ident_quoted = false; return IDENT; @@ -1918,3 +1919,16 @@ dealSahrpComment(core_yyscan_t yyscanner) } } +static char* CopyIdentifier(const char* ident, int len, bool warn) +{ + char* result = NULL; + int i; + errno_t ret = 0; + result = (char*)palloc(len + 1); + ret = strncpy_s(result, len + 1, ident, len); + securec_check(ret, "\0", "\0"); + if (len >= NAMEDATALEN) + truncate_identifier(result, len, warn); + + return result; +} diff --git a/contrib/dolphin/plugin_postgres.cpp b/contrib/dolphin/plugin_postgres.cpp index 30d16e882f1e91c992c8742b1f4eb3ef6addaec3..ea589856aee54ed3956027095fb1dab777040d04 100644 --- a/contrib/dolphin/plugin_postgres.cpp +++ b/contrib/dolphin/plugin_postgres.cpp @@ -370,6 +370,18 @@ void init_session_vars(void) check_b_db_timestamp, assign_b_db_timestamp, NULL); + DefineCustomIntVariable("lower_case_table_names", + gettext_noop("used to set the sensitive of identifier"), + NULL, + &GetSessionContext()->lower_case_table_names, + 1, + 0, + 2, + PGC_USERSET, + 0, + NULL, + NULL, + NULL); } static void execute_sql_file() diff --git a/contrib/dolphin/sql/case_sensitive_test/alter_table.sql b/contrib/dolphin/sql/case_sensitive_test/alter_table.sql new file mode 100644 index 0000000000000000000000000000000000000000..26d1b506f3fec3dd8aedda9f1379d7bd3fdf28cc --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/alter_table.sql @@ -0,0 +1,419 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; + +-- +--FOR BLACKLIST FEATURE: REFERENCES/INHERITS/WITH OIDS/RULE/CREATE TYPE/DOMAIN is not supported. +-- +-- +-- ALTER_TABLE +-- add attribute +-- + +CREATE TABLE Tmp (initial int4); + +COMMENT ON TABLE tmp_wrong IS 'table comment'; +COMMENT ON TABLE Tmp IS 'table comment'; +COMMENT ON TABLE Tmp IS NULL; + +ALTER TABLE Tmp ADD COLUMN xmin integer; -- fails + +ALTER TABLE Tmp ADD COLUMN a int4 default 3; + +ALTER TABLE Tmp ADD COLUMN b name; + +ALTER TABLE Tmp ADD COLUMN c text; + +ALTER TABLE Tmp ADD COLUMN d float8; + +ALTER TABLE Tmp ADD COLUMN e float4; + +ALTER TABLE Tmp ADD COLUMN f int2; + +ALTER TABLE Tmp ADD COLUMN g polygon; + +ALTER TABLE Tmp ADD COLUMN h abstime; + +ALTER TABLE Tmp ADD COLUMN i char; + +ALTER TABLE Tmp ADD COLUMN j abstime[]; + +ALTER TABLE Tmp ADD COLUMN k int4; + +ALTER TABLE Tmp ADD COLUMN l tid; + +ALTER TABLE Tmp ADD COLUMN m xid; + +ALTER TABLE Tmp ADD COLUMN n oidvector; + +--ALTER TABLE Tmp ADD COLUMN o lock; +ALTER TABLE Tmp ADD COLUMN p smgr; + +ALTER TABLE Tmp ADD COLUMN q point; + +ALTER TABLE Tmp ADD COLUMN r lseg; + +ALTER TABLE Tmp ADD COLUMN s path; + +ALTER TABLE Tmp ADD COLUMN t box; + +ALTER TABLE Tmp ADD COLUMN u tinterval; + +ALTER TABLE Tmp ADD COLUMN v timestamp; + +ALTER TABLE Tmp ADD COLUMN w interval; + +ALTER TABLE Tmp ADD COLUMN x float8[]; + +ALTER TABLE Tmp ADD COLUMN y float4[]; + +ALTER TABLE Tmp ADD COLUMN z int2[]; + +INSERT INTO Tmp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, p, q, r, s, t, u, + v, w, x, y, z) + VALUES (4, 'name', 'text', 4.1, 4.1, 2, '(4.1,4.1,3.1,3.1)', + 'Mon May 1 00:30:30 1995', 'c', '{Mon May 1 00:30:30 1995, Monday Aug 24 14:43:07 1992, epoch}', + 314159, '(1,1)', '512', + '1 2 3 4 5 6 7 8', 'magnetic disk', '(1.1,1.1)', '(4.1,4.1,3.1,3.1)', + '(0,2,4.1,4.1,3.1,3.1)', '(4.1,4.1,3.1,3.1)', '["epoch" "infinity"]', + 'epoch', '01:00:10', '{1.0,2.0,3.0,4.0}', '{1.0,2.0,3.0,4.0}', '{1,2,3,4}'); + +SELECT * FROM Tmp; + +DROP TABLE Tmp; + +-- the wolf bug - schema mods caused inconsistent row descriptors +CREATE TABLE Tmp ( + initial int4 +); + +ALTER TABLE Tmp ADD COLUMN a int4; + +ALTER TABLE Tmp ADD COLUMN b name; + +ALTER TABLE Tmp ADD COLUMN c text; + +ALTER TABLE Tmp ADD COLUMN d float8; + +ALTER TABLE Tmp ADD COLUMN e float4; + +ALTER TABLE Tmp ADD COLUMN f int2; + +ALTER TABLE Tmp ADD COLUMN g polygon; + +ALTER TABLE Tmp ADD COLUMN h abstime; + +ALTER TABLE Tmp ADD COLUMN i char; + +ALTER TABLE Tmp ADD COLUMN j abstime[]; + +ALTER TABLE Tmp ADD COLUMN k int4; + +ALTER TABLE Tmp ADD COLUMN l tid; + +ALTER TABLE Tmp ADD COLUMN m xid; + +ALTER TABLE Tmp ADD COLUMN n oidvector; + +--ALTER TABLE Tmp ADD COLUMN o lock; +ALTER TABLE Tmp ADD COLUMN p smgr; + +ALTER TABLE Tmp ADD COLUMN q point; + +ALTER TABLE Tmp ADD COLUMN r lseg; + +ALTER TABLE Tmp ADD COLUMN s path; + +ALTER TABLE Tmp ADD COLUMN t box; + +ALTER TABLE Tmp ADD COLUMN u tinterval; + +ALTER TABLE Tmp ADD COLUMN v timestamp; + +ALTER TABLE Tmp ADD COLUMN w interval; + +ALTER TABLE Tmp ADD COLUMN x float8[]; + +ALTER TABLE Tmp ADD COLUMN y float4[]; + +ALTER TABLE Tmp ADD COLUMN z int2[]; + +INSERT INTO Tmp (a, b, c, d, e, f, g, h, i, j, k, l, m, n, p, q, r, s, t, u, + v, w, x, y, z) + VALUES (4, 'name', 'text', 4.1, 4.1, 2, '(4.1,4.1,3.1,3.1)', + 'Mon May 1 00:30:30 1995', 'c', '{Mon May 1 00:30:30 1995, Monday Aug 24 14:43:07 1992, epoch}', + 314159, '(1,1)', '512', + '1 2 3 4 5 6 7 8', 'magnetic disk', '(1.1,1.1)', '(4.1,4.1,3.1,3.1)', + '(0,2,4.1,4.1,3.1,3.1)', '(4.1,4.1,3.1,3.1)', '["epoch" "infinity"]', + 'epoch', '01:00:10', '{1.0,2.0,3.0,4.0}', '{1.0,2.0,3.0,4.0}', '{1,2,3,4}'); + +SELECT * FROM Tmp; + +DROP TABLE Tmp; + + +-- +-- rename - check on both non-temp and temp tables +-- +CREATE TABLE Tmp (regtable int); +-- Enforce use of COMMIT instead of 2PC for temporary objects +\set VERBOSITY verbose +-- CREATE TEMP TABLE Tmp (tmptable int); + +ALTER TABLE Tmp RENAME TO Tmp_new; + +-- SELECT * FROM Tmp; +-- SELECT * FROM Tmp_new; + +-- ALTER TABLE Tmp RENAME TO Tmp_new2; + +SELECT * FROM Tmp; -- should fail +SELECT *, FROM Tmp; -- should fail +SELECT * FROM Tmp_new; +-- SELECT * FROM Tmp_new2; + +DROP TABLE Tmp_new; +-- DROP TABLE Tmp_new2; +CREATE TABLE Tmp (ch1 character(1)); +insert into Tmp values ('asdv'); +DROP TABLE Tmp; +\set VERBOSITY default +-- ALTER TABLE ... RENAME on non-table relations +-- renaming indexes (FIXME: this should probably test the index's functionality) +ALTER INDEX IF EXISTS __onek_unique1 RENAME TO tmp_onek_unique1; +ALTER INDEX IF EXISTS __tmp_onek_unique1 RENAME TO onek_unique1; + +ALTER INDEX onek_unique1 RENAME TO tmp_onek_unique1; +ALTER INDEX tmp_onek_unique1 RENAME TO onek_unique1; +-- renaming views +CREATE VIEW tmp_view (unique1) AS SELECT unique1 FROM Tenk1; +ALTER TABLE tmp_view RENAME TO tmp_view_new; + +-- hack to ensure we get an indexscan here +ANALYZE Tenk1; +set enable_seqscan to off; +set enable_bitmapscan to off; +-- 5 values, sorted +SELECT unique1 FROM Tenk1 WHERE unique1 < 5 ORDER BY unique1; +reset enable_seqscan; +reset enable_bitmapscan; + +DROP VIEW tmp_view_new; +-- toast-like relation name +alter table Stud_Emp rename to pg_toast_stud_emp; +alter table pg_toast_stud_emp rename to Stud_Emp; + +-- renaming index should rename constraint as well +ALTER TABLE Onek ADD CONSTRAINT onek_unique1_constraint UNIQUE (unique1); +ALTER INDEX onek_unique1_constraint RENAME TO onek_unique1_constraint_foo; +ALTER TABLE Onek DROP CONSTRAINT onek_unique1_constraint_foo; + +-- renaming constraint +ALTER TABLE Onek ADD CONSTRAINT onek_check_constraint CHECK (unique1 >= 0); +ALTER TABLE Onek RENAME CONSTRAINT onek_check_constraint TO onek_check_constraint_foo; +ALTER TABLE Onek DROP CONSTRAINT onek_check_constraint_foo; + +-- renaming constraint should rename index as well +ALTER TABLE Onek ADD CONSTRAINT onek_unique1_constraint UNIQUE (unique1); +DROP INDEX onek_unique1_constraint; -- to see whether it's there +ALTER TABLE Onek RENAME CONSTRAINT onek_unique1_constraint TO onek_unique1_constraint_foo; +DROP INDEX onek_unique1_constraint_foo; -- to see whether it's there +ALTER TABLE Onek DROP CONSTRAINT onek_unique1_constraint_foo; + +-- renaming constraints vs. Inheritance +CREATE TABLE Constraint_Rename_Test (a int CONSTRAINT con1 CHECK (a > 0), b int, c int); +\d "Constraint_Rename_Test" +CREATE TABLE Constraint_Rename_Test2 (a int CONSTRAINT con1 CHECK (a > 0), d int) InheRITS (Constraint_Rename_Test); +\d "Constraint_Rename_Test2" +ALTER TABLE Constraint_Rename_Test2 RENAME CONSTRAINT con1 TO con1foo; -- fail +ALTER TABLE ONLY Constraint_Rename_Test RENAME CONSTRAINT con1 TO con1foo; -- fail +ALTER TABLE Constraint_Rename_Test RENAME CONSTRAINT con1 TO con1foo; -- ok +\d "Constraint_Rename_Test" +\d "Constraint_Rename_Test2" +ALTER TABLE Constraint_Rename_Test ADD CONSTRAINT con2 CHECK (b > 0) NO InheRIT; +ALTER TABLE ONLY Constraint_Rename_Test RENAME CONSTRAINT con2 TO con2foo; -- ok +ALTER TABLE Constraint_Rename_Test RENAME CONSTRAINT con2foo TO con2bar; -- ok +\d "Constraint_Rename_Test" +\d "Constraint_Rename_Test2" +ALTER TABLE Constraint_Rename_Test ADD CONSTRAINT con3 PRIMARY KEY (a); +ALTER TABLE Constraint_Rename_Test RENAME CONSTRAINT con3 TO con3foo; -- ok +\d "Constraint_Rename_Test" +\d "Constraint_Rename_Test2" +DROP TABLE Constraint_Rename_Test2; +DROP TABLE Constraint_Rename_Test; +ALTER TABLE IF EXISTS Constraint_Rename_Test ADD CONSTRAINT con4 UNIQUE (a); + +-- FOREIGN KEY CONSTRAINT adding TEST + +CREATE TABLE Tmp2 (a int primary key); + +CREATE TABLE Tmp3 (a int, b int); + +CREATE TABLE Tmp4 (a int, b int, unique(a,b)); + +CREATE TABLE Tmp5 (a int, b int); + +-- Insert rows into Tmp2 (PKTABLE) +INSERT INTO Tmp2 values (1); +INSERT INTO Tmp2 values (2); +INSERT INTO Tmp2 values (3); +INSERT INTO Tmp2 values (4); + +-- Insert rows into Tmp3 +INSERT INTO Tmp3 values (1,10); +INSERT INTO Tmp3 values (1,20); +INSERT INTO Tmp3 values (5,50); + +-- Try (and fail) to add constraint due to invalid source columns +ALTER TABLE Tmp3 add constraint tmpconstr foreign key(c) references Tmp2 match full; + +-- Try (and fail) to add constraint due to invalide destination columns explicitly given +ALTER TABLE Tmp3 add constraint tmpconstr foreign key(a) references Tmp2(b) match full; + +-- Try (and fail) to add constraint due to invalid data +ALTER TABLE Tmp3 add constraint tmpconstr foreign key (a) references Tmp2 match full; + +-- Delete failing row +DELETE FROM Tmp3 where a=5; + +-- Try (and succeed) +ALTER TABLE Tmp3 add constraint tmpconstr foreign key (a) references Tmp2 match full; +ALTER TABLE Tmp3 drop constraint tmpconstr; + +INSERT INTO Tmp3 values (5,50); + +-- Try NOT VALID and then VALIDATE CONSTRAINT, but fails. Delete failure then re-validate +ALTER TABLE Tmp3 add constraint tmpconstr foreign key (a) references Tmp2 match full NOT VALID; +ALTER TABLE Tmp3 validate constraint tmpconstr; + +-- Delete failing row +DELETE FROM Tmp3 where a=5; + +-- Try (and succeed) and repeat to show it works on already valid constraint +ALTER TABLE Tmp3 validate constraint tmpconstr; +ALTER TABLE Tmp3 validate constraint tmpconstr; + +-- Try a non-verified CHECK constraint +ALTER TABLE Tmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10); -- fail +ALTER TABLE Tmp3 ADD CONSTRAINT b_greater_than_ten CHECK (b > 10) NOT VALID; -- succeeds +ALTER TABLE Tmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- fails +DELETE FROM Tmp3 WHERE NOT b > 10; +ALTER TABLE Tmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds +ALTER TABLE Tmp3 VALIDATE CONSTRAINT b_greater_than_ten; -- succeeds + +-- Test inherited NOT VALID CHECK constraints +select * from Tmp3; +CREATE TABLE Tmp6 () INHERITS (Tmp3); +CREATE TABLE Tmp7 () INHERITS (Tmp3); + +INSERT INTO Tmp6 VALUES (6, 30), (7, 16); +ALTER TABLE Tmp3 ADD CONSTRAINT b_le_20 CHECK (b <= 20) NOT VALID; +ALTER TABLE Tmp3 VALIDATE CONSTRAINT b_le_20; -- fails +DELETE FROM Tmp6 WHERE b > 20; +ALTER TABLE Tmp3 VALIDATE CONSTRAINT b_le_20; -- succeeds + +-- An already validated constraint must not be revalidated +CREATE FUNCTION boo(int) RETURNS int IMMUTABLE STRICT LANGUAGE plpgsql AS $$ BEGIN RAISE NOTICE 'boo: %', $1; RETURN $1; END; $$; +INSERT INTO Tmp7 VALUES (8, 18); +set client_min_messages=WARNING; +ALTER TABLE Tmp7 ADD CONSTRAINT identity CHECK (b = boo(b)); +reset client_min_messages; +ALTER TABLE Tmp3 ADD CONSTRAINT IDENTITY check (b = boo(b)) NOT VALID; +set client_min_messages=WARNING; +ALTER TABLE Tmp3 VALIDATE CONSTRAINT identity; +reset client_min_messages; + +-- Try (and fail) to create constraint from Tmp5(a) to Tmp4(a) - unique constraint on +-- Tmp4 is a,b + +ALTER TABLE Tmp5 add constraint tmpconstr foreign key(a) references Tmp4(a) match full; + +DROP TABLE Tmp7; + +DROP TABLE Tmp6; + +DROP TABLE Tmp5; + +DROP TABLE Tmp4; + +DROP TABLE Tmp3; + +DROP TABLE Tmp2; + +-- NOT VALID with plan invalidation -- ensure we don't use a constraint for +-- exclusion until validated +set constraint_exclusion TO 'partition'; +create table NV_Parent (d date); +create table NV_Child_2010 () Inherits (NV_Parent); +create table NV_Child_2011 () Inherits (NV_Parent); +alter table NV_Child_2010 add check (d between '2010-01-01'::date and '2010-12-31'::date) not valid; +alter table NV_Child_2011 add check (d between '2011-01-01'::date and '2011-12-31'::date) not valid; +explain (costs off) select * from NV_Parent where d between '2011-08-01' and '2011-08-31'; +create table NV_Child_2009 (check (d between '2009-01-01'::date and '2009-12-31'::date)) Inherits (NV_Parent); +explain (costs off) select * from NV_Parent where d between '2011-08-01'::date and '2011-08-31'::date; +explain (costs off) select * from NV_Parent where d between '2009-08-01'::date and '2009-08-31'::date; +-- after validation, the constraint should be used +alter table NV_Child_2011 VALIDATE CONSTRAINT nv_child_2011_d_check; +explain (costs off) select * from NV_Parent where d between '2009-08-01'::date and '2009-08-31'::date; + + +-- Foreign key adding test with mixed types + +-- Note: these tables are TEMP to avoid name conflicts when this test +-- is run in parallel with foreign_key.sql. + +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +INSERT INTO PKTABLE VALUES(42); +CREATE TABLE FKTABLE (ftest1 inet); +-- This next should fail, because int=inet does not exist +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references PKTABLE; +-- This should also fail for the same reason, but here we +-- give the column name +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references PKTABLE(ptest1); +DROP TABLE FKTABLE; +-- This should succeed, even though they are different types, +-- because int=int8 exists and is a member of the integer opfamily +CREATE TABLE FKTABLE (ftest1 int8); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references PKTABLE; +-- Check it actually works +INSERT INTO FKTABLE VALUES(42); -- should succeed +INSERT INTO FKTABLE VALUES(43); -- should fail +DROP TABLE FKTABLE; +-- This should fail, because we'd have to cast numeric to int which is +-- not an implicit coercion (or use numeric=numeric, but that's not part +-- of the integer opfamily) +CREATE TABLE FKTABLE (ftest1 numeric); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references PKTABLE; +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; +-- On the other hand, this should work because int implicitly promotes to +-- numeric, and we allow promotion on the FK side +CREATE TABLE PKTABLE (ptest1 numeric PRIMARY KEY); +INSERT INTO PKTABLE VALUES(42); +CREATE TABLE FKTABLE (ftest1 int); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1) references PKTABLE; +-- Check it actually works +INSERT INTO FKTABLE VALUES(42); -- should succeed +INSERT INTO FKTABLE VALUES(43); -- should fail +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, + PRIMARY KEY(ptest1, ptest2)); +-- This should fail, because we just chose really odd types +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) references PKTABLE; +DROP TABLE FKTABLE; +-- Again, so should this... +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) + references PKTABLE(ptest1, ptest2); +DROP TABLE FKTABLE; +-- This fails because we mixed up the column ordering +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet); +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest1, ftest2) + references PKTABLE(ptest2, ptest1); +-- As does this... +ALTER TABLE FKTABLE ADD FOREIGN KEY(ftest2, ftest1) + references PKTABLE(ptest1, ptest2); + +-- temp tables should go away by themselves, need not drop them. diff --git a/contrib/dolphin/sql/case_sensitive_test/analyze_commands.sql b/contrib/dolphin/sql/case_sensitive_test/analyze_commands.sql new file mode 100644 index 0000000000000000000000000000000000000000..2e4b1746b8cd6d638834c54fe8d9381366707649 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/analyze_commands.sql @@ -0,0 +1,39 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +create schema analyze_commands; +set search_path to analyze_commands; + +drop table if exists T1; +create table T1(a int, b int, c int); +insert into T1 values(generate_series(1,10),generate_series(1,2),generate_series(1,2)); +set default_statistics_target=100; +analyze T1; +analyze T1((b,c)); +select * from pg_stats where tablename = 'T1' order by attname; +select * from pg_catalog.pg_ext_stats; + +drop table if exists T1; +create table T1(a int, b int, c int); +insert into T1 values(generate_series(1,10),generate_series(1,2),generate_series(1,2)); +set default_statistics_target=100; +analyze; +select * from pg_stats where tablename = 'T1' order by attname; +select * from pg_catalog.pg_ext_stats; + +drop table if exists T1; +create table T1(a int, b int, c int); +insert into T1 values(generate_series(1,10),generate_series(1,2),generate_series(1,2)); +set default_statistics_target=-2; +analyze T1; +analyze T1((b,c)); +select * from pg_stats where tablename = 'T1' order by attname; +select * from pg_catalog.pg_ext_stats; + +insert into T1 values(generate_series(1,10),generate_series(3,4),generate_series(3,4)); +analyze; +select * from pg_stats where tablename = 'T1' order by attname; +select * from pg_catalog.pg_ext_stats; + +reset search_path; +drop schema analyze_commands cascade; + diff --git a/contrib/dolphin/sql/case_sensitive_test/cluster.sql b/contrib/dolphin/sql/case_sensitive_test/cluster.sql new file mode 100644 index 0000000000000000000000000000000000000000..812a2204600b53f84f8132c8463388d89fc325c3 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/cluster.sql @@ -0,0 +1,211 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- CLUSTER +-- + +CREATE TABLE Clstr_tst_s (rf_a SERIAL PRIMARY KEY, + b INT); + +CREATE TABLE Clstr_tst (a SERIAL PRIMARY KEY, + b INT, + c TEXT, + d TEXT + ); + +CREATE INDEX Clstr_tst_b ON Clstr_tst (b); +CREATE INDEX Clstr_tst_c ON Clstr_tst (c); +CREATE INDEX Clstr_tst_c_b ON Clstr_tst (c,b); +CREATE INDEX Clstr_tst_b_c ON Clstr_tst (b,c); + +INSERT INTO Clstr_tst_s (b) VALUES (0); +INSERT INTO Clstr_tst_s (b) SELECT b FROM Clstr_tst_s; +INSERT INTO Clstr_tst_s (b) SELECT b FROM Clstr_tst_s; +INSERT INTO Clstr_tst_s (b) SELECT b FROM Clstr_tst_s; +INSERT INTO Clstr_tst_s (b) SELECT b FROM Clstr_tst_s; +INSERT INTO Clstr_tst_s (b) SELECT b FROM Clstr_tst_s; + +-- CREATE TABLE Clstr_tst_inh () INHERITS (Clstr_tst); + +INSERT INTO Clstr_tst (b, c) VALUES (11, 'once'); +INSERT INTO Clstr_tst (b, c) VALUES (10, 'diez'); +INSERT INTO Clstr_tst (b, c) VALUES (31, 'treinta y uno'); +INSERT INTO Clstr_tst (b, c) VALUES (22, 'veintidos'); +INSERT INTO Clstr_tst (b, c) VALUES (3, 'tres'); +INSERT INTO Clstr_tst (b, c) VALUES (20, 'veinte'); +INSERT INTO Clstr_tst (b, c) VALUES (23, 'veintitres'); +INSERT INTO Clstr_tst (b, c) VALUES (21, 'veintiuno'); +INSERT INTO Clstr_tst (b, c) VALUES (4, 'cuatro'); +INSERT INTO Clstr_tst (b, c) VALUES (14, 'catorce'); +INSERT INTO Clstr_tst (b, c) VALUES (2, 'dos'); +INSERT INTO Clstr_tst (b, c) VALUES (18, 'dieciocho'); +INSERT INTO Clstr_tst (b, c) VALUES (27, 'veintisiete'); +INSERT INTO Clstr_tst (b, c) VALUES (25, 'veinticinco'); +INSERT INTO Clstr_tst (b, c) VALUES (13, 'trece'); +INSERT INTO Clstr_tst (b, c) VALUES (28, 'veintiocho'); +INSERT INTO Clstr_tst (b, c) VALUES (32, 'treinta y dos'); +INSERT INTO Clstr_tst (b, c) VALUES (5, 'cinco'); +INSERT INTO Clstr_tst (b, c) VALUES (29, 'veintinueve'); +INSERT INTO Clstr_tst (b, c) VALUES (1, 'uno'); +INSERT INTO Clstr_tst (b, c) VALUES (24, 'veinticuatro'); +INSERT INTO Clstr_tst (b, c) VALUES (30, 'treinta'); +INSERT INTO Clstr_tst (b, c) VALUES (12, 'doce'); +INSERT INTO Clstr_tst (b, c) VALUES (17, 'diecisiete'); +INSERT INTO Clstr_tst (b, c) VALUES (9, 'nueve'); +INSERT INTO Clstr_tst (b, c) VALUES (19, 'diecinueve'); +INSERT INTO Clstr_tst (b, c) VALUES (26, 'veintiseis'); +INSERT INTO Clstr_tst (b, c) VALUES (15, 'quince'); +INSERT INTO Clstr_tst (b, c) VALUES (7, 'siete'); +INSERT INTO Clstr_tst (b, c) VALUES (16, 'dieciseis'); +INSERT INTO Clstr_tst (b, c) VALUES (8, 'ocho'); +-- This entry is needed to test that TOASTED values are copied correctly. +INSERT INTO Clstr_tst (b, c, d) VALUES (6, 'seis', repeat('xyzzy', 100000)); + +CLUSTER Clstr_tst_c ON Clstr_tst; + +SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a, b, c; +SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a; +SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY b; +SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY c; + +-- Verify that inheritance link still works +-- INSERT INTO Clstr_tst_inh VALUES (0, 100, 'in child table'); +SELECT a,b,c,substring(d for 30), length(d) from Clstr_tst ORDER BY a, b, c; + +-- Verify that foreign key link still works +INSERT INTO Clstr_tst (b, c) VALUES (1111, 'this should fail'); + +SELECT conname FROM pg_constraint WHERE conrelid = 'Clstr_tst'::regclass +ORDER BY 1; + + +SELECT relname, relkind, + EXISTS(SELECT 1 FROM pg_class WHERE oid = c.reltoastrelid) AS hastoast +FROM pg_class c WHERE relname LIKE 'Clstr_tst%' ORDER BY relname; + +-- Verify that indisclustered is correctly set +SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2 +WHERE pg_class.oid=indexrelid + AND indrelid=pg_class_2.oid + AND pg_class_2.relname = 'Clstr_tst' + AND indisclustered; + +-- Try changing indisclustered +ALTER TABLE Clstr_tst CLUSTER ON Clstr_tst_b_c; +SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2 +WHERE pg_class.oid=indexrelid + AND indrelid=pg_class_2.oid + AND pg_class_2.relname = 'Clstr_tst' + AND indisclustered; + +-- Try turning off all clustering +ALTER TABLE Clstr_tst SET WITHOUT CLUSTER; +SELECT pg_class.relname FROM pg_index, pg_class, pg_class AS pg_class_2 +WHERE pg_class.oid=indexrelid + AND indrelid=pg_class_2.oid + AND pg_class_2.relname = 'Clstr_tst' + AND indisclustered; + +-- Verify that clustering all tables does in fact cluster the right ones +CREATE USER Clstr_user PASSWORD 'ttest@123'; +CREATE TABLE Clstr_1 (a INT PRIMARY KEY); +CREATE TABLE Clstr_2 (a INT PRIMARY KEY); +CREATE TABLE Clstr_3 (a INT PRIMARY KEY); +ALTER TABLE Clstr_1 OWNER TO Clstr_user; +ALTER TABLE Clstr_3 OWNER TO Clstr_user; +GRANT SELECT ON Clstr_2 TO Clstr_user; +INSERT INTO Clstr_1 VALUES (2); +INSERT INTO Clstr_1 VALUES (1); +INSERT INTO Clstr_2 VALUES (2); +INSERT INTO Clstr_2 VALUES (1); +INSERT INTO Clstr_3 VALUES (2); +INSERT INTO Clstr_3 VALUES (1); + +-- "CLUSTER " on a table that hasn't been clustered +CLUSTER Clstr_2; + +CLUSTER Clstr_1_pkey ON Clstr_1; +CLUSTER Clstr_2 USING Clstr_2_pkey; +SELECT * FROM Clstr_1 UNION ALL + SELECT * FROM Clstr_2 UNION ALL + SELECT * FROM Clstr_3 + ORDER BY 1; + +-- revert to the original state +DELETE FROM Clstr_1; +DELETE FROM Clstr_2; +DELETE FROM Clstr_3; +INSERT INTO Clstr_1 VALUES (2); +INSERT INTO Clstr_1 VALUES (1); +INSERT INTO Clstr_2 VALUES (2); +INSERT INTO Clstr_2 VALUES (1); +INSERT INTO Clstr_3 VALUES (2); +INSERT INTO Clstr_3 VALUES (1); + +-- this user can only cluster Clstr_1 and Clstr_3, but the latter +-- has not been clustered +SET SESSION AUTHORIZATION Clstr_user PASSWORD 'ttest@123'; +CLUSTER; +SELECT * FROM Clstr_1 UNION ALL + SELECT * FROM Clstr_2 UNION ALL + SELECT * FROM Clstr_3 + ORDER BY 1; + +-- cluster a single table using the indisclustered bit previously set +DELETE FROM Clstr_1; +INSERT INTO Clstr_1 VALUES (2); +INSERT INTO Clstr_1 VALUES (1); +CLUSTER Clstr_1; +SELECT * FROM Clstr_1 +ORDER BY 1; + +-- Test MVCC-safety of cluster. There isn't much we can do to verify the +-- results with a single backend... + +CREATE TABLE clustertest (key_a int PRIMARY KEY); + +INSERT INTO clustertest VALUES (10); +INSERT INTO clustertest VALUES (20); +INSERT INTO clustertest VALUES (30); +INSERT INTO clustertest VALUES (40); +INSERT INTO clustertest VALUES (50); + +-- Use a transaction so that updates are not committed when CLUSTER sees 'em +START TRANSACTION; + +-- Test update where the old row version is found first in the scan +UPDATE clustertest SET key_a = 100 WHERE key_a = 10; + +-- Test update where the new row version is found first in the scan +UPDATE clustertest SET key_a = 35 WHERE key_a = 40; + +-- Test longer update chain +UPDATE clustertest SET key_a = 60 WHERE key_a = 50; +UPDATE clustertest SET key_a = 70 WHERE key_a = 60; +UPDATE clustertest SET key_a = 80 WHERE key_a = 70; + +SELECT * FROM clustertest ORDER BY 1; +CLUSTER clustertest_pkey ON clustertest; +SELECT * FROM clustertest ORDER BY 1; + +COMMIT; + +SELECT * FROM clustertest ORDER BY 1; + +-- check that temp tables can be clustered +-- Enforce use of COMMIT instead of 2PC for temporary objects +RESET SESSION AUTHORIZATION; +SET SESSION AUTHORIZATION Clstr_user PASSWORD 'ttest@123'; + +create temp table Clstr_temp (col1 int primary key, col2 text); +insert into Clstr_temp values (2, 'two'), (1, 'one'); +cluster Clstr_temp using Clstr_temp_pkey; +select * from Clstr_temp order by 1; +drop table Clstr_temp; +DROP TABLE Clstr_2; +DROP TABLE Clstr_tst_s; + +-- clean up +\c - +RESET SESSION AUTHORIZATION; +DROP USER "Clstr_user" CASCADE; diff --git a/contrib/dolphin/sql/case_sensitive_test/create_foreign_table.sql b/contrib/dolphin/sql/case_sensitive_test/create_foreign_table.sql new file mode 100644 index 0000000000000000000000000000000000000000..c50b94a39845638ca1b2c7756596cb27c5d68d90 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/create_foreign_table.sql @@ -0,0 +1,68 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; + +-- +--Create Foreign table in Normal mode. +-- +create foreign table Foreign_t1 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'text', location 'gsfs://127.0.0.1:12345/t1.data', delimiter '|'); + +create foreign table Foreign_t2 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'csv', location 'gsfs://127.0.0.1:12345/t1.data', delimiter '|', mode 'normal'); + +-- +--Create Foreign table in Shared mode +-- +create foreign table Foreign_t3 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'text', location 'gsfs://127.0.0.1:12345/t1.data', delimiter '|', mode 'shared'); + +create foreign table Foreign_t4 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'csv', location '/data/t1.data', delimiter '|', mode 'shared'); + +create foreign table Foreign_t5 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'text', location '/data/t1.data', delimiter '|', mode 'shared'); + +-- +--Create Foreign table in Private mode +-- +create foreign table Foreign_t6 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'text', location '/data/t1.data', delimiter '|', mode 'private'); + +create foreign table Foreign_t7 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'csv', location '/data/t1.data', delimiter '|', mode 'private'); + +create foreign table Foreign_t8 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'csv', location 'gsfs://127.0.0.1:12345/t1.data', delimiter '|', mode 'private'); + + +----- +create foreign table Foreign_t9 ( + c1 int, + c2 varchar(17) +)server gsmpp_server options(format 'csv', location '/data/t1.data', delimiter '|', mode 'private', fill_missing_fields 'true'); + +drop foreign table Foreign_t1; +drop foreign table Foreign_t2; +drop foreign table Foreign_t3; +drop foreign table Foreign_t4; +drop foreign table Foreign_t5; +drop foreign table Foreign_t6; +drop foreign table Foreign_t7; +drop foreign table Foreign_t8; +drop foreign table Foreign_t9; diff --git a/contrib/dolphin/sql/case_sensitive_test/create_index.sql b/contrib/dolphin/sql/case_sensitive_test/create_index.sql new file mode 100644 index 0000000000000000000000000000000000000000..c94e0c7c6bb093403285151d2bde55c4ae17dc05 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/create_index.sql @@ -0,0 +1,971 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- CREATE_INDEX +-- Create ancillary data structures (i.e. indices) +-- + +-- +-- BTREE +-- +CREATE INDEX onek_unique1 ON Onek USING btree(unique1 int4_ops); + +CREATE INDEX onek_unique2 ON Onek USING btree(unique2 int4_ops); + +CREATE INDEX onek_hundred ON Onek USING btree(hundred int4_ops); + +CREATE INDEX onek_stringu1 ON Onek USING btree(stringu1 name_ops); + +CREATE INDEX tenk1_unique1 ON Tenk1 USING btree(unique1 int4_ops); + +CREATE INDEX tenk1_unique2 ON Tenk1 USING btree(unique2 int4_ops); + +CREATE INDEX tenk1_hundred ON Tenk1 USING btree(hundred int4_ops); + +CREATE INDEX tenk1_thous_tenthous ON Tenk1 (thousand, tenthous); + +CREATE INDEX tenk2_unique1 ON Tenk2 USING btree(unique1 int4_ops); + +CREATE INDEX tenk2_unique2 ON Tenk2 USING btree(unique2 int4_ops); + +CREATE INDEX tenk2_hundred ON Tenk2 USING btree(hundred int4_ops); + +CREATE INDEX rix ON Road USING btree (name text_ops); + +CREATE INDEX iix ON iHighway USING btree (name text_ops); + +CREATE INDEX six ON sHighway USING btree (name text_ops); + +-- test comments +COMMENT ON INDEX six_wrong IS 'bad index'; +COMMENT ON INDEX six IS 'good index'; +COMMENT ON INDEX six IS NULL; + +-- +-- BTREE ascending/descending cases +-- +-- we load int4/text from pure descending data (each key is a new +-- low key) and name/f8 from pure ascending data (each key is a new +-- high key). we had a bug where new low keys would sometimes be +-- "lost". +-- +CREATE INDEX bt_i4_index ON BT_i4_heap USING btree (seqno int4_ops); + +CREATE INDEX bt_name_index ON BT_name_heap USING btree (seqno name_ops); + +CREATE INDEX bt_txt_index ON BT_txt_heap USING btree (seqno text_ops); + +CREATE INDEX bt_f8_index ON BT_f8_heap USING btree (seqno float8_ops); + +-- +-- BTREE partial indices +-- +CREATE INDEX onek2_u1_prtl ON Onek2 USING btree(unique1 int4_ops) + where unique1 < 20 or unique1 > 980; + +CREATE INDEX onek2_u2_prtl ON Onek2 USING btree(unique2 int4_ops) + where stringu1 < 'B'; + +CREATE INDEX onek2_stu1_prtl ON Onek2 USING btree(stringu1 name_ops) + where Onek2.stringu1 >= 'J' and Onek2.stringu1 < 'K'; + +-- +-- GiST (rtree-equivalent opclasses only) +-- +CREATE INDEX grect2ind ON Fast_emp4000 USING gist (home_base); + +CREATE INDEX gpolygonind ON Polygon_tbl USING gist (f1); + +CREATE INDEX gcircleind ON Circle_tbl USING gist (f1); + +INSERT INTO point_tbl(f1) VALUES (NULL); + +CREATE INDEX gpointind ON point_tbl USING gist (f1); + + +--CREATE TABLE gPolygon_tbl AS +-- SELECT polygon(home_base) AS f1 FROM Slow_emp4000; +--INSERT INTO gPolygon_tbl VALUES ( '(1000,0,0,1000)' ); +--INSERT INTO gPolygon_tbl VALUES ( '(0,1000,1000,1000)' ); + +--CREATE TABLE gCircle_tbl AS +-- SELECT circle(home_base) AS f1 FROM Slow_emp4000; + +--CREATE INDEX ggpolygonind ON gPolygon_tbl USING gist (f1); + +--CREATE INDEX ggcircleind ON gCircle_tbl USING gist (f1); + +-- +-- SP-GiST +-- + +CREATE TABLE Quad_point_tbl AS + SELECT point(unique1,unique2) AS p FROM Tenk1; + +INSERT INTO Quad_point_tbl + SELECT '(333.0,400.0)'::point FROM generate_series(1,1000); + +INSERT INTO Quad_point_tbl VALUES (NULL), (NULL), (NULL); + +CREATE INDEX sp_quad_ind ON Quad_point_tbl USING spgist (p); + +CREATE TABLE KD_point_tbl AS SELECT * FROM Quad_point_tbl; + +CREATE INDEX SP_kd_ind ON KD_point_tbl USING spgist (p kd_point_ops); + +CREATE TABLE Suffix_text_tbl AS + SELECT name AS t FROM Road WHERE name !~ '^[0-9]'; + +INSERT INTO Suffix_text_tbl + SELECT 'P0123456789abcdef' FROM generate_series(1,1000); +INSERT INTO Suffix_text_tbl VALUES ('P0123456789abcde'); +INSERT INTO Suffix_text_tbl VALUES ('P0123456789abcdefF'); + +CREATE INDEX sp_suff_ind ON Suffix_text_tbl USING spgist (t); + +-- +-- Test GiST and SP-GiST indexes +-- + +-- get non-indexed results for comparison purposes + +SET enable_seqscan = ON; +SET enable_indexscan = OFF; +SET enable_bitmapscan = OFF; + +SELECT * FROM Fast_emp4000 + WHERE home_base @ '(200,200),(2000,1000)'::box + ORDER BY (home_base[0])[0]; + +SELECT count(*) FROM Fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; + +SELECT count(*) FROM Fast_emp4000 WHERE home_base IS NULL; + +SELECT * FROM Polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon + ORDER BY (poly_center(f1))[0]; + +SELECT * FROM Circle_tbl WHERE f1 && circle(point(1,-2), 1) + ORDER BY area(f1); + +--SELECT count(*) FROM gPolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; + +--SELECT count(*) FROM gCircle_tbl WHERE f1 && '<(500,500),500>'::circle; + +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; + +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; + +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; + +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; + +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; + +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; + +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; + +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; + +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; + +SELECT * FROM point_tbl ORDER BY f1 <-> '0,1'; + +SELECT * FROM point_tbl WHERE f1 IS NULL; + +SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1'; + +SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; + +SELECT count(*) FROM Quad_point_tbl WHERE p IS NULL; + +SELECT count(*) FROM Quad_point_tbl WHERE p IS NOT NULL; + +SELECT count(*) FROM Quad_point_tbl; + +SELECT count(*) FROM Quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; + +SELECT count(*) FROM Quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; + +SELECT count(*) FROM Quad_point_tbl WHERE p << '(5000, 4000)'; + +SELECT count(*) FROM Quad_point_tbl WHERE p >> '(5000, 4000)'; + +SELECT count(*) FROM Quad_point_tbl WHERE p <^ '(5000, 4000)'; + +SELECT count(*) FROM Quad_point_tbl WHERE p >^ '(5000, 4000)'; + +SELECT count(*) FROM Quad_point_tbl WHERE p ~= '(4585, 365)'; + +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdef'; + +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcde'; + +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdefF'; + +SELECT count(*) FROM Suffix_text_tbl WHERE t < 'Aztec Ct '; + +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<~ 'Aztec Ct '; + +SELECT count(*) FROM Suffix_text_tbl WHERE t <= 'Aztec Ct '; + +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<=~ 'Aztec Ct '; + +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Aztec Ct '; + +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Worth St '; + +SELECT count(*) FROM Suffix_text_tbl WHERE t >= 'Worth St '; + +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>=~ 'Worth St '; + +SELECT count(*) FROM Suffix_text_tbl WHERE t > 'Worth St '; + +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>~ 'Worth St '; + +-- Now check the results from plain indexscan +SET enable_seqscan = OFF; +SET enable_indexscan = ON; +SET enable_bitmapscan = OFF; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Fast_emp4000 + WHERE home_base @ '(200,200),(2000,1000)'::box + ORDER BY (home_base[0])[0]; +SELECT * FROM Fast_emp4000 + WHERE home_base @ '(200,200),(2000,1000)'::box + ORDER BY (home_base[0])[0]; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; +SELECT count(*) FROM Fast_emp4000 WHERE home_base && '(1000,1000,0,0)'::box; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Fast_emp4000 WHERE home_base IS NULL; +SELECT count(*) FROM Fast_emp4000 WHERE home_base IS NULL; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon + ORDER BY (poly_center(f1))[0]; +SELECT * FROM Polygon_tbl WHERE f1 ~ '((1,1),(2,2),(2,1))'::polygon + ORDER BY (poly_center(f1))[0]; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Circle_tbl WHERE f1 && circle(point(1,-2), 1) + ORDER BY area(f1); +SELECT * FROM Circle_tbl WHERE f1 && circle(point(1,-2), 1) + ORDER BY area(f1); + +--EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +--SELECT count(*) FROM gPolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; +--SELECT count(*) FROM gPolygon_tbl WHERE f1 && '(1000,1000,0,0)'::polygon; + +--EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +--SELECT count(*) FROM gCircle_tbl WHERE f1 && '<(500,500),500>'::circle; +--SELECT count(*) FROM gCircle_tbl WHERE f1 && '<(500,500),500>'::circle; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; +SELECT count(*) FROM point_tbl WHERE f1 <@ box '(0,0,100,100)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; +SELECT count(*) FROM point_tbl WHERE box '(0,0,100,100)' @> f1; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; +SELECT count(*) FROM point_tbl WHERE f1 <@ polygon '(0,0),(0,100),(100,100),(50,50),(100,0),(0,0)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; +SELECT count(*) FROM point_tbl WHERE f1 <@ circle '<(50,50),50>'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; +SELECT count(*) FROM point_tbl p WHERE p.f1 << '(0.0, 0.0)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; +SELECT count(*) FROM point_tbl p WHERE p.f1 >> '(0.0, 0.0)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; +SELECT count(*) FROM point_tbl p WHERE p.f1 <^ '(0.0, 0.0)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; +SELECT count(*) FROM point_tbl p WHERE p.f1 >^ '(0.0, 0.0)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; +SELECT count(*) FROM point_tbl p WHERE p.f1 ~= '(-5, -12)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM point_tbl ORDER BY f1 <-> '0,1'; +SELECT * FROM point_tbl ORDER BY f1 <-> '0,1'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM point_tbl WHERE f1 IS NULL; +SELECT * FROM point_tbl WHERE f1 IS NULL; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1'; +SELECT * FROM point_tbl WHERE f1 IS NOT NULL ORDER BY f1 <-> '0,1'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; +SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p IS NULL; +SELECT count(*) FROM Quad_point_tbl WHERE p IS NULL; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p IS NOT NULL; +SELECT count(*) FROM Quad_point_tbl WHERE p IS NOT NULL; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl; +SELECT count(*) FROM Quad_point_tbl; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; +SELECT count(*) FROM Quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; +SELECT count(*) FROM Quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p << '(5000, 4000)'; +SELECT count(*) FROM Quad_point_tbl WHERE p << '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p >> '(5000, 4000)'; +SELECT count(*) FROM Quad_point_tbl WHERE p >> '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p <^ '(5000, 4000)'; +SELECT count(*) FROM Quad_point_tbl WHERE p <^ '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p >^ '(5000, 4000)'; +SELECT count(*) FROM Quad_point_tbl WHERE p >^ '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p ~= '(4585, 365)'; +SELECT count(*) FROM Quad_point_tbl WHERE p ~= '(4585, 365)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p <@ box '(200,200,1000,1000)'; +SELECT count(*) FROM KD_point_tbl WHERE p <@ box '(200,200,1000,1000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE box '(200,200,1000,1000)' @> p; +SELECT count(*) FROM KD_point_tbl WHERE box '(200,200,1000,1000)' @> p; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p << '(5000, 4000)'; +SELECT count(*) FROM KD_point_tbl WHERE p << '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p >> '(5000, 4000)'; +SELECT count(*) FROM KD_point_tbl WHERE p >> '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p <^ '(5000, 4000)'; +SELECT count(*) FROM KD_point_tbl WHERE p <^ '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p >^ '(5000, 4000)'; +SELECT count(*) FROM KD_point_tbl WHERE p >^ '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p ~= '(4585, 365)'; +SELECT count(*) FROM KD_point_tbl WHERE p ~= '(4585, 365)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdef'; +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdef'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcde'; +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcde'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdefF'; +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdefF'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t < 'Aztec Ct '; +SELECT count(*) FROM Suffix_text_tbl WHERE t < 'Aztec Ct '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<~ 'Aztec Ct '; +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<~ 'Aztec Ct '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t <= 'Aztec Ct '; +SELECT count(*) FROM Suffix_text_tbl WHERE t <= 'Aztec Ct '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<=~ 'Aztec Ct '; +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<=~ 'Aztec Ct '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Aztec Ct '; +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Aztec Ct '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Worth St '; +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Worth St '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t >= 'Worth St '; +SELECT count(*) FROM Suffix_text_tbl WHERE t >= 'Worth St '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>=~ 'Worth St '; +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>=~ 'Worth St '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t > 'Worth St '; +SELECT count(*) FROM Suffix_text_tbl WHERE t > 'Worth St '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>~ 'Worth St '; +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>~ 'Worth St '; + +-- Now check the results from bitmap indexscan +SET enable_seqscan = OFF; +SET enable_indexscan = OFF; +SET enable_bitmapscan = ON; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; +SELECT * FROM point_tbl WHERE f1 <@ '(-10,-10),(10,10)':: box ORDER BY f1 <-> '0,1'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p IS NULL; +SELECT count(*) FROM Quad_point_tbl WHERE p IS NULL; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p IS NOT NULL; +SELECT count(*) FROM Quad_point_tbl WHERE p IS NOT NULL; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl; +SELECT count(*) FROM Quad_point_tbl; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; +SELECT count(*) FROM Quad_point_tbl WHERE p <@ box '(200,200,1000,1000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; +SELECT count(*) FROM Quad_point_tbl WHERE box '(200,200,1000,1000)' @> p; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p << '(5000, 4000)'; +SELECT count(*) FROM Quad_point_tbl WHERE p << '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p >> '(5000, 4000)'; +SELECT count(*) FROM Quad_point_tbl WHERE p >> '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p <^ '(5000, 4000)'; +SELECT count(*) FROM Quad_point_tbl WHERE p <^ '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p >^ '(5000, 4000)'; +SELECT count(*) FROM Quad_point_tbl WHERE p >^ '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Quad_point_tbl WHERE p ~= '(4585, 365)'; +SELECT count(*) FROM Quad_point_tbl WHERE p ~= '(4585, 365)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p <@ box '(200,200,1000,1000)'; +SELECT count(*) FROM KD_point_tbl WHERE p <@ box '(200,200,1000,1000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE box '(200,200,1000,1000)' @> p; +SELECT count(*) FROM KD_point_tbl WHERE box '(200,200,1000,1000)' @> p; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p << '(5000, 4000)'; +SELECT count(*) FROM KD_point_tbl WHERE p << '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p >> '(5000, 4000)'; +SELECT count(*) FROM KD_point_tbl WHERE p >> '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p <^ '(5000, 4000)'; +SELECT count(*) FROM KD_point_tbl WHERE p <^ '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p >^ '(5000, 4000)'; +SELECT count(*) FROM KD_point_tbl WHERE p >^ '(5000, 4000)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM KD_point_tbl WHERE p ~= '(4585, 365)'; +SELECT count(*) FROM KD_point_tbl WHERE p ~= '(4585, 365)'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdef'; +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdef'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcde'; +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcde'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdefF'; +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'P0123456789abcdefF'; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t < 'Aztec Ct '; +SELECT count(*) FROM Suffix_text_tbl WHERE t < 'Aztec Ct '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<~ 'Aztec Ct '; +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<~ 'Aztec Ct '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t <= 'Aztec Ct '; +SELECT count(*) FROM Suffix_text_tbl WHERE t <= 'Aztec Ct '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<=~ 'Aztec Ct '; +SELECT count(*) FROM Suffix_text_tbl WHERE t ~<=~ 'Aztec Ct '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Aztec Ct '; +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Aztec Ct '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Worth St '; +SELECT count(*) FROM Suffix_text_tbl WHERE t = 'Worth St '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t >= 'Worth St '; +SELECT count(*) FROM Suffix_text_tbl WHERE t >= 'Worth St '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>=~ 'Worth St '; +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>=~ 'Worth St '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t > 'Worth St '; +SELECT count(*) FROM Suffix_text_tbl WHERE t > 'Worth St '; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>~ 'Worth St '; +SELECT count(*) FROM Suffix_text_tbl WHERE t ~>~ 'Worth St '; + +RESET enable_seqscan; +RESET enable_indexscan; +RESET enable_bitmapscan; + +-- +-- GIN over int[] and text[] +-- +-- Note: GIN currently supports only bitmap scans, not plain indexscans +-- + +SET enable_seqscan = OFF; +SET enable_indexscan = OFF; +SET enable_bitmapscan = ON; + +CREATE INDEX intarrayidx ON Array_index_op_test USING gin (i); + +explain (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Array_index_op_test WHERE i @> '{32}' ORDER BY seqno; + +SELECT * FROM Array_index_op_test WHERE i @> '{32}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i && '{32}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i @> '{17}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i && '{17}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i @> '{32,17}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i && '{32,17}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i <@ '{38,34,32,89}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i = '{47,77}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i = '{}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i @> '{}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i && '{}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i <@ '{}' ORDER BY seqno; +SELECT * FROM Array_op_test WHERE i = '{NULL}' ORDER BY seqno; +SELECT * FROM Array_op_test WHERE i @> '{NULL}' ORDER BY seqno; +SELECT * FROM Array_op_test WHERE i && '{NULL}' ORDER BY seqno; +SELECT * FROM Array_op_test WHERE i <@ '{NULL}' ORDER BY seqno; + +CREATE INDEX textarrayidx ON Array_index_op_test USING gin (t); + +explain (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Array_index_op_test WHERE t @> '{AAAAAAAA72908}' ORDER BY seqno; + +SELECT * FROM Array_index_op_test WHERE t @> '{AAAAAAAA72908}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t && '{AAAAAAAA72908}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t @> '{AAAAAAAAAA646}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t && '{AAAAAAAAAA646}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t @> '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t && '{AAAAAAAA72908,AAAAAAAAAA646}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t <@ '{AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t = '{AAAAAAAAAA646,A87088}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t = '{}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t @> '{}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t && '{}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t <@ '{}' ORDER BY seqno; + +-- And try it with a multicolumn GIN index + +DROP INDEX intarrayidx, textarrayidx; + +CREATE INDEX botharrayidx ON Array_index_op_test USING gin (i, t); + +SELECT * FROM Array_index_op_test WHERE i @> '{32}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i && '{32}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t @> '{AAAAAAA80240}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t && '{AAAAAAA80240}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i @> '{32}' AND t && '{AAAAAAA80240}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE i && '{32}' AND t @> '{AAAAAAA80240}' ORDER BY seqno; +SELECT * FROM Array_index_op_test WHERE t = '{}' ORDER BY seqno; +SELECT * FROM Array_op_test WHERE i = '{NULL}' ORDER BY seqno; +SELECT * FROM Array_op_test WHERE i <@ '{NULL}' ORDER BY seqno; + +RESET enable_seqscan; +RESET enable_indexscan; +RESET enable_bitmapscan; + +-- +-- Test GIN index's reloptions +-- +CREATE INDEX gin_relopts_test ON Array_index_op_test USING gin (i) + WITH (FASTUPDATE=on, GIN_PENDING_LIST_LIMIT=128); +\d+ "gin_relopts_test" + +-- +-- HASH +-- +CREATE INDEX hash_i4_index ON Hash_i4_heap USING hash (random int4_ops); + +CREATE INDEX hash_name_index ON Hash_name_heap USING hash (random name_ops); + +CREATE INDEX hash_txt_index ON Hash_txt_heap USING hash (random text_ops); + +CREATE INDEX hash_f8_index ON Hash_f8_heap USING hash (random float8_ops); + +-- CREATE INDEX hash_ovfl_index ON hash_ovfl_heap USING hash (x int4_ops); + + +-- +-- Test functional index +-- +-- PGXC: Here replication is used to ensure correct index creation +-- when a non-shippable expression is used. +-- PGXCTODO: this should be removed once global constraints are supported +CREATE TABLE func_index_heap (f1 text, f2 text) ; +CREATE UNIQUE INDEX func_index_index on func_index_heap (textcat(f1,f2)); + +INSERT INTO func_index_heap VALUES('ABC','DEF'); +INSERT INTO func_index_heap VALUES('AB','CDEFG'); +INSERT INTO func_index_heap VALUES('QWE','RTY'); +-- this should fail because of unique index: +INSERT INTO func_index_heap VALUES('ABCD', 'EF'); +-- but this shouldn't: +INSERT INTO func_index_heap VALUES('QWERTY'); + + +-- +-- Same test, expressional index +-- +DROP TABLE func_index_heap; +-- PGXC: Here replication is used to ensure correct index creation +-- when a non-shippable expression is used. +-- PGXCTODO: this should be removed once global constraints are supported +CREATE TABLE func_index_heap (f1 text, f2 text) ; +CREATE UNIQUE INDEX func_index_index on func_index_heap ((f1 || f2) text_ops); + +INSERT INTO func_index_heap VALUES('ABC','DEF'); +INSERT INTO func_index_heap VALUES('AB','CDEFG'); +INSERT INTO func_index_heap VALUES('QWE','RTY'); +-- this should fail because of unique index: +INSERT INTO func_index_heap VALUES('ABCD', 'EF'); +-- but this shouldn't: +INSERT INTO func_index_heap VALUES('QWERTY'); + +-- +-- Also try building functional, expressional, and partial indexes on +-- tables that already contain data. +-- +create unique index hash_f8_index_1 on Hash_f8_heap(abs(random)); +create unique index hash_f8_index_2 on Hash_f8_heap((seqno + 1), random); +create unique index hash_f8_index_3 on Hash_f8_heap(random) where seqno > 1000; + +-- +-- Try some concurrent index builds +-- +-- Unfortunately this only tests about half the code paths because there are +-- no concurrent updates happening to the table at the same time. + +CREATE TABLE concur_heap (f1 text, f2 text); +-- empty table +CREATE INDEX CONCURRENTLY concur_index1 ON concur_heap(f2,f1); +INSERT INTO concur_heap VALUES ('a','b'); +INSERT INTO concur_heap VALUES ('b','b'); +-- unique index +CREATE UNIQUE INDEX CONCURRENTLY concur_index2 ON concur_heap(f1); +-- check if constraint is set up properly to be enforced +INSERT INTO concur_heap VALUES ('b','x'); +-- check if constraint is enforced properly at build time +CREATE UNIQUE INDEX CONCURRENTLY concur_index3 ON concur_heap(f2); +-- test that expression indexes and partial indexes work concurrently +CREATE INDEX CONCURRENTLY concur_index4 on concur_heap(f2) WHERE f1='a'; +CREATE INDEX CONCURRENTLY concur_index5 on concur_heap(f2) WHERE f1='x'; +-- here we also check that you can default the index name +CREATE INDEX CONCURRENTLY on concur_heap((f2||f1)); + +-- You can't do a concurrent index build in a transaction +START TRANSACTION; +CREATE INDEX CONCURRENTLY concur_index7 ON concur_heap(f1); +COMMIT; + +-- But you can do a regular index build in a transaction +START TRANSACTION; +CREATE INDEX std_index on concur_heap(f2); +COMMIT; + +-- check to make sure that the failed indexes were cleaned up properly and the +-- successful indexes are created properly. Notably that they do NOT have the +-- "invalid" flag set. + +\d "concur_heap" + +-- +-- Try some concurrent index drops +-- +DROP INDEX CONCURRENTLY "concur_index2"; -- works +DROP INDEX CONCURRENTLY IF EXISTS "concur_index2"; -- notice + +-- failures +DROP INDEX CONCURRENTLY "concur_index2", "concur_index3"; +START TRANSACTION; +DROP INDEX CONCURRENTLY "concur_index5"; +ROLLBACK; + +-- successes +DROP INDEX CONCURRENTLY IF EXISTS "concur_index3"; +DROP INDEX CONCURRENTLY "concur_index4"; +DROP INDEX CONCURRENTLY "concur_index5"; +DROP INDEX CONCURRENTLY "concur_index1"; +DROP INDEX CONCURRENTLY "concur_heap_expr_idx"; + +\d "concur_heap" + +DROP TABLE concur_heap; + +-- +-- Test ADD CONSTRAINT USING INDEX +-- + +CREATE TABLE cwi_test( a int , b varchar(10), c char); + +-- add some data so that all tests have something to work with. + +INSERT INTO cwi_test VALUES(1, 2), (3, 4), (5, 6); + +CREATE UNIQUE INDEX cwi_uniq_idx ON cwi_test(a , b); +ALTER TABLE cwi_test ADD primary key USING INDEX cwi_uniq_idx; + +\d "cwi_test" + +CREATE UNIQUE INDEX cwi_uniq2_idx ON cwi_test(b , a); +ALTER TABLE cwi_test DROP CONSTRAINT cwi_uniq_idx, + ADD CONSTRAINT cwi_replaced_pkey PRIMARY KEY + USING INDEX cwi_uniq2_idx; + +\d "cwi_test" + +DROP INDEX cwi_replaced_pkey; -- Should fail; a constraint depends on it + +DROP TABLE cwi_test; + +-- +-- Tests for IS NULL/IS NOT NULL with b-tree indexes +-- + +SELECT unique1, unique2 INTO onek_with_null FROM Onek; +INSERT INTO onek_with_null (unique1,unique2) VALUES (NULL, -1), (NULL, NULL); +CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2,unique1); + +SET enable_seqscan = OFF; +SET enable_indexscan = ON; +SET enable_bitmapscan = ON; + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; + +DROP INDEX onek_nulltest; + +CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2 desc,unique1); + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; + +DROP INDEX onek_nulltest; + +CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2 desc nulls last,unique1); + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; + +DROP INDEX onek_nulltest; + +CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2 nulls first,unique1); + +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique2 IS NOT NULL; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NOT NULL AND unique1 > 500; +SELECT count(*) FROM onek_with_null WHERE unique1 IS NULL AND unique1 > 500; + +DROP INDEX onek_nulltest; + +-- Check initial-positioning logic too + +CREATE UNIQUE INDEX onek_nulltest ON onek_with_null (unique2); + +SET enable_seqscan = OFF; +SET enable_indexscan = ON; +SET enable_bitmapscan = OFF; + +SELECT unique1, unique2 FROM onek_with_null + ORDER BY unique2 LIMIT 2; +SELECT unique1, unique2 FROM onek_with_null WHERE unique2 >= -1 + ORDER BY unique2 LIMIT 2; +SELECT unique1, unique2 FROM onek_with_null WHERE unique2 >= 0 + ORDER BY unique2 LIMIT 2; + +SELECT unique1, unique2 FROM onek_with_null + ORDER BY unique2 DESC LIMIT 2; +SELECT unique1, unique2 FROM onek_with_null WHERE unique2 >= -1 + ORDER BY unique2 DESC LIMIT 2; +SELECT unique1, unique2 FROM onek_with_null WHERE unique2 < 999 + ORDER BY unique2 DESC LIMIT 2; + +RESET enable_seqscan; +RESET enable_indexscan; +RESET enable_bitmapscan; + +DROP TABLE onek_with_null; + +-- +-- Check bitmap index path planning +-- + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT * FROM Tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42); +SELECT * FROM Tenk1 + WHERE thousand = 42 AND (tenthous = 1 OR tenthous = 3 OR tenthous = 42); + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT count(*) FROM Tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); +SELECT count(*) FROM Tenk1 + WHERE hundred = 42 AND (thousand = 42 OR thousand = 99); + +-- +-- Check behavior with duplicate index column contents +-- + +CREATE TABLE dupindexcols AS + SELECT unique1 as id, stringu2::text as f1 FROM Tenk1; +CREATE INDEX dupindexcols_i ON dupindexcols (f1, id, f1 text_pattern_ops); +ANALYZE dupindexcols; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) + SELECT count(*) FROM dupindexcols + WHERE f1 > 'WA' and id < 1000 and f1 ~<~ 'YX'; +SELECT count(*) FROM dupindexcols + WHERE f1 > 'WA' and id < 1000 and f1 ~<~ 'YX'; + +-- +-- Check ordering of =ANY indexqual results (bug in 9.2.0) +-- + +vacuum analyze Tenk1; -- ensure we get consistent plans here + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT unique1 FROM Tenk1 +WHERE unique1 IN (1,42,7) +ORDER BY unique1; + +SELECT unique1 FROM Tenk1 +WHERE unique1 IN (1,42,7) +ORDER BY unique1; + +EXPLAIN (NUM_NODES OFF, NODES OFF, COSTS OFF) +SELECT thousand, tenthous FROM Tenk1 +WHERE thousand < 2 AND tenthous IN (1001,3000) +ORDER BY thousand; + +SELECT thousand, tenthous FROM Tenk1 +WHERE thousand < 2 AND tenthous IN (1001,3000) +ORDER BY thousand; + +--test for relpages and reltuples of pg_class +create table test_table(a int, b int); +create table test_table_col(a int, b int) with (orientation=column); +insert into test_table select generate_series(1,100),generate_series(1,100); +insert into test_table_col select * from test_table; +analyze test_table; +analyze test_table_col; + +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table'; +create index test_table_idx1 on test_table(a,b); +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table'; +analyze test_table; +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table_idx1'; + +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table_col'; +create index test_table_col_idx1 on test_table_col(a,b); +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table_col'; +analyze test_table_col; +select relpages>0 as relpages,reltuples>0 as reltuples from pg_class where relname='test_table_col_idx1'; + +--test nestloop index param path +create table t_hash_table (a int, b int); +create table t_rep_table (a int, b int) ; +create index idx_rep_table on t_rep_table(a); + +explain (costs off) select /*+ rows(t_rep_table #100000) */ * from t_hash_table where t_hash_table.a in (select a from t_rep_table); +explain (costs off) select /*+ rows(t_rep_table #100000) */ * from t_hash_table where '1' = '0' or t_hash_table.a in (select a from t_rep_table); + +create index test0 on t_rep_table(rownum); +create index test0 on t_rep_table(sin(a), sin(rownum)); +create index test0 on t_rep_table(sin(a), sin(rownum+1)); + +drop index idx_rep_table; +drop table t_hash_table; +drop table t_rep_table; + +drop index test_table_idx1; +drop index test_table_col_idx1; +drop table test_table; +drop table test_table_col; diff --git a/contrib/dolphin/sql/case_sensitive_test/create_table.sql b/contrib/dolphin/sql/case_sensitive_test/create_table.sql new file mode 100644 index 0000000000000000000000000000000000000000..3f329d3553148d9f55f42fe776906dbb3edf577b --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/create_table.sql @@ -0,0 +1,458 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; + +-- +-- CREATE_TABLE +-- +-- CREATE TABLE SYNTAX +-- +-- CLASS DEFINITIONS +-- +CREATE TABLE Src(a int) with(autovacuum_enabled = off); +insert into Src values(1); + +CREATE TABLE Hobbies_r ( + name text, + person text +) with(autovacuum_enabled = off); + +CREATE TABLE Equipment_r ( + name text, + hobby text +) with(autovacuum_enabled = off); + +CREATE TABLE Onek ( + unique1 int4, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) with(autovacuum_enabled = off); + +CREATE TABLE Onek2 AS SELECT * FROM Onek; + +CREATE TABLE Tenk1 ( + unique1 int4, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) with(autovacuum_enabled = off); + +CREATE TABLE Tenk2 ( + unique1 int4, + unique2 int4, + two int4, + four int4, + ten int4, + twenty int4, + hundred int4, + thousand int4, + twothousand int4, + fivethous int4, + tenthous int4, + odd int4, + even int4, + stringu1 name, + stringu2 name, + string4 name +) with(autovacuum_enabled = off); + + +CREATE TABLE Person ( + name text, + age int4, + location point +); + + +CREATE TABLE Emp ( + name text, + age int4, + location point, + salary int4, + manager name +) with(autovacuum_enabled = off); + + +CREATE TABLE Student ( + name text, + age int4, + location point, + gpa float8 +); + + +CREATE TABLE Stud_Emp ( + name text, + age int4, + location point, + salary int4, + manager name, + gpa float8, + percent int4 +) with(autovacuum_enabled = off); + +CREATE TABLE City ( + name name, + location box, + budget city_budget +) with(autovacuum_enabled = off); + +CREATE TABLE Dept ( + dname name, + mgrname text +) with(autovacuum_enabled = off); + +CREATE TABLE Slow_emp4000 ( + home_base box +) with(autovacuum_enabled = off); + +CREATE TABLE Fast_emp4000 ( + home_base box +) with(autovacuum_enabled = off); + +CREATE TABLE Road ( + name text, + thepath path +); + +CREATE TABLE iHighway( + name text, + thepath path +) with(autovacuum_enabled = off); + +CREATE TABLE sHighway ( + surface text, + name text, + thepath path +) with(autovacuum_enabled = off); + +CREATE TABLE Real_City ( + pop int4, + cname text, + outline path +) with(autovacuum_enabled = off); + +-- +-- test the "star" operators a bit more thoroughly -- this time, +-- throw in lots of NULL fields... +-- +-- a is the type root +-- b and c Inherit from a (one-level single Inheritance) +-- d Inherits from b and c (two-level multiple Inheritance) +-- e Inherits from c (two-level single Inheritance) +-- f Inherits from e (three-level single Inheritance) +-- +CREATE TABLE a_Star ( + class char, + a int4 +) with(autovacuum_enabled = off); + +CREATE TABLE b_Star ( + b text, + class char, + a int4 +) with(autovacuum_enabled = off); + +CREATE TABLE c_Star ( + c name, + class char, + a int4 +) with(autovacuum_enabled = off); + +CREATE TABLE d_Star ( + d float8, + b text, + class char, + a int4, + c name +) with(autovacuum_enabled = off); + +CREATE TABLE e_Star ( + e int2, + c name, + class char, + a int4 +) with(autovacuum_enabled = off); + +CREATE TABLE f_Star ( + f polygon, + e int2, + c name, + class char, + a int4 +) with(autovacuum_enabled = off); + +CREATE TABLE AggTest ( + a int2, + b float4 +) with(autovacuum_enabled = off); + +CREATE TABLE Hash_i4_heap ( + seqno int4, + random int4 +) with(autovacuum_enabled = off); + +CREATE TABLE Hash_name_heap ( + seqno int4, + random name +) with(autovacuum_enabled = off); + +CREATE TABLE Hash_txt_heap ( + seqno int4, + random text +) with(autovacuum_enabled = off); + +-- PGXC: Here replication is used to ensure correct index creation +-- when a non-shippable expression is used. +-- PGXCTODO: this should be removed once global constraints are supported +CREATE TABLE Hash_f8_heap ( + seqno int4, + random float8 +) with(autovacuum_enabled = off); + +-- don't include the hash_ovfl_heap stuff in the distribution +-- the data set is too large for what it's worth +-- +-- CREATE TABLE hash_ovfl_heap ( +-- x int4, +-- y int4 +-- ); + +CREATE TABLE BT_i4_heap ( + seqno int4, + random int4 +) with(autovacuum_enabled = off); + +CREATE TABLE BT_name_heap ( + seqno name, + random int4 +) with(autovacuum_enabled = off); + +CREATE TABLE BT_txt_heap ( + seqno text, + random int4 +); + +CREATE TABLE BT_f8_heap ( + seqno float8, + random int4 +) with(autovacuum_enabled = off); + +CREATE TABLE Array_op_test ( + seqno int4, + i int4[], + t text[] +) with(autovacuum_enabled = off); + +CREATE TABLE Array_index_op_test ( + seqno int4, + i int4[], + t text[] +) with(autovacuum_enabled = off); + +CREATE TABLE IF NOT EXISTS Test_tsvector( + t text, + a tsvector +); + +CREATE TABLE IF NOT EXISTS Test_tsvector( + t text +) with(autovacuum_enabled = off); + +CREATE UNLOGGED TABLE unlogged1 (a int primary key); -- OK +INSERT INTO unlogged1 VALUES (42); +CREATE UNLOGGED TABLE public.unlogged2 (a int primary key); -- also OK +CREATE UNLOGGED TABLE pg_temp.unlogged3 (a int primary key); -- not OK +CREATE TABLE pg_temp.implicitly_temp (a int primary key); -- OK +CREATE TEMP TABLE explicitly_temp (a int primary key); -- also OK +CREATE TEMP TABLE pg_temp.doubly_temp (a int primary key); -- also OK +CREATE TEMP TABLE public.temp_to_perm (a int primary key); -- not OK +DROP TABLE unlogged1, public.unlogged2; + +-- +-- CREATE TABLE AS TEST CASE: Expect the column typemod info is not lost on DN +-- +CREATE TABLE HW_create_as_test11(C_CHAR CHAR(102400)); +CREATE TABLE HW_create_as_test12(C_CHAR) as SELECT C_CHAR FROM HW_create_as_test11; +CREATE TABLE HW_create_as_test13 (C_CHAR CHAR(102400)); +ALTER TABLE HW_create_as_test13 InheRIT HW_create_as_test12; +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test13; +DROP TABLE HW_create_as_test11; + +CREATE TABLE HW_create_as_test11(C_INT int); +CREATE TABLE HW_create_as_test12(C_INT) as SELECT C_INT FROM HW_create_as_test11; +CREATE TABLE HW_create_as_test13 (C_INT int); +ALTER TABLE HW_create_as_test13 InheRIT HW_create_as_test12; +DROP TABLE HW_create_as_test13; +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test11; + +CREATE TABLE HW_create_as_test11(COL1 numeric(10,2)); +CREATE TABLE HW_create_as_test12(COL1) as SELECT COL1 FROM HW_create_as_test11; +CREATE TABLE HW_create_as_test13 (COL1 numeric(10,2)); +ALTER TABLE HW_create_as_test13 InheRIT HW_create_as_test12; +DROP TABLE HW_create_as_test13; +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test11; + +CREATE TABLE HW_create_as_test11(COL1 timestamp(1)); +CREATE TABLE HW_create_as_test12(COL1) as SELECT COL1 FROM HW_create_as_test11; +CREATE TABLE HW_create_as_test13 (COL1 timestamp(1)); +ALTER TABLE HW_create_as_test13 InheRIT HW_create_as_test12; +DROP TABLE HW_create_as_test13; +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test11; + +CREATE TABLE HW_create_as_test11(COL1 int[2][2]); +CREATE TABLE HW_create_as_test12(COL1) as SELECT COL1 FROM HW_create_as_test11; +CREATE TABLE HW_create_as_test13 (COL1 int[2][2]); +ALTER TABLE HW_create_as_test13 InheRIT HW_create_as_test12; +DROP TABLE HW_create_as_test13; +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test11; + +create table HW_create_as_test11(col1 int); +insert into HW_create_as_test11 values(1); +insert into HW_create_as_test11 values(2); +create table HW_create_as_test12 as select * from HW_create_as_test11 with no data; +select count(*) from HW_create_as_test12; +explain (analyze on, costs off) create table HW_create_as_test13 as select * from HW_create_as_test11 with no data; +drop table HW_create_as_test11; +drop table HW_create_as_test12; +drop table HW_create_as_test13; + +CREATE TABLE HW_create_as_test11(COL1 int); +insert into HW_create_as_test11 values(1); +insert into HW_create_as_test11 values(2); +CREATE TABLE HW_create_as_test12 as SELECT '001' col1, COL1 col2 FROM HW_create_as_test11; +select * from HW_create_as_test12 order by 1, 2; +DROP TABLE HW_create_as_test12; +DROP TABLE HW_create_as_test11; + +-- Zero column table is not supported any more. +CREATE TABLE Zero_column_table_test1(); +CREATE TABLE Zero_column_table_test2(); + +CREATE TABLE Zero_column_table_test3(a INT); +ALTER TABLE Zero_column_table_test3 DROP COLUMN a; +DROP TABLE Zero_column_table_test3; + +CREATE TABLE Zero_column_table_test6() with (orientation = column); +CREATE TABLE Zero_column_table_test7() with (orientation = column); +CREATE TABLE Zero_column_table_test8(a INT) with (orientation = column); +ALTER TABLE Zero_column_table_test8 DROP COLUMN a; +DROP TABLE Zero_column_table_test8; + +--test create table of pg_node_tree type +create table PG_node_tree_tbl11(id int,name pg_node_tree); +create table PG_node_tree_tbl12 as select * from pg_type; + +-- test unreserved keywords for table name +CREATE TABLE App(a int); +CREATE TABLE Movement(a int); +CREATE TABLE Pool(a int); +CREATE TABLE Profile(a int); +CREATE TABLE Resource(a int); +CREATE TABLE Store(a int); +CREATE TABLE Than(a int); +CREATE TABLE Workload(a int); + +DROP TABLE App; +DROP TABLE Movement; +DROP TABLE Pool; +DROP TABLE Profile; +DROP TABLE Resource; +DROP TABLE Store; +DROP TABLE Than; +DROP TABLE Workload; + +-- test orientation +CREATE TABLE Orientation_test_1 (c1 int) WITH (orientation = column); +CREATE TABLE Orientation_test_2 (c1 int) WITH (orientation = 'column'); +CREATE TABLE Orientation_test_3 (c1 int) WITH (orientation = "column"); +CREATE TABLE Orientation_test_4 (c1 int) WITH (orientation = row); +CREATE TABLE Orientation_test_5 (c1 int) WITH (orientation = 'row'); +CREATE TABLE Orientation_test_6 (c1 int) WITH (orientation = "row"); + +DROP TABLE Orientation_test_1; +DROP TABLE Orientation_test_2; +DROP TABLE Orientation_test_3; +DROP TABLE Orientation_test_4; +DROP TABLE Orientation_test_5; +DROP TABLE Orientation_test_6; + +CREATE SCHEMA "TEST"; +CREATE SCHEMA "SCHEMA_TEST"; + +CREATE TABLE "SCHEMA_TEST"."Table" ( + column1 bigint, + column2 bigint +); + +CREATE TABLE "TEST"."Test_Table"( + clm1 "SCHEMA_TEST"."Table", + clm2 bigint); + +select * from "TEST"."Test_Table"; + +set current_schema=information_schema; +create table Test_info(a int, b int); +insert into Test_info values(1,2),(2,3),(3,4),(4,5); +\d+ "Test_info" +\d+ "sql_features" +explain (verbose on, costs off) select count(*) from sql_features; +select count(*) from sql_features; + +explain (verbose on, costs off) select * from Test_info; +select count(*) from Test_info; +drop table Test_info; +reset current_schema; + +create table t_Serial(a int, b serial); +create temp table t_Tmp(a int, b serial); +create temp table t_Tmp(like t_Serial); +set enable_beta_features = on; +create temp table t_Tmp(like t_Serial); +select nextval('"t_Tmp_b_seq"'); +reset enable_beta_features; +set default_statistics_target = -50; +analyze t_Serial; +drop table t_Serial; +drop table t_Tmp; + +-- schema.table +CREATE TABLE public.Test_indirection1(a int); +-- catalog.schema.table +CREATE TABLE table_name_test_db.public.Test_indirection2(a int); +-- error +CREATE TABLE unknown_obj.table_name_test_db.public.Test_indirection3(a int); + +drop table "TEST"."Test_Table"; +drop table "SCHEMA_TEST"."Table"; +drop schema "TEST"; +drop schema "SCHEMA_TEST"; diff --git a/contrib/dolphin/sql/case_sensitive_test/create_table_like.sql b/contrib/dolphin/sql/case_sensitive_test/create_table_like.sql new file mode 100644 index 0000000000000000000000000000000000000000..e6400e8dc91edbd7ae55b1ba585c4042911eb1aa --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/create_table_like.sql @@ -0,0 +1,181 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; + +-- +--FOR BLACKLIST FEATURE: SEQUENCE、EXCLUDE、InheRITS is not supported. +-- + +/* Test Inheritance of structure (LIKE) */ +CREATE TABLE Inhx (xx text DEFAULT 'text'); + +/* + * Test double Inheritance + * + * Ensure that defaults are NOT included unless + * INCLUDING DEFAULTS is specified + */ +CREATE TABLE Ctla (aa TEXT); +CREATE TABLE Ctlb (bb TEXT) InheRITS (Ctla); + +CREATE TABLE Foo (LIKE nonexistent); + +CREATE TABLE Inhe (ee text, LIKE Inhx) Inherits (Ctlb); +INSERT INTO Inhe VALUES ('ee-col1', 'ee-col2', DEFAULT, 'ee-col4'); +SELECT * FROM Inhe; /* Columns aa, bb, xx value NULL, ee */ +SELECT * FROM Inhx; /* Empty set since LIKE Inherits structure only */ +SELECT * FROM Ctlb; /* Has ee entry */ +SELECT * FROM Ctla; /* Has ee entry */ + +CREATE TABLE inhf (LIKE Inhx, LIKE Inhx); /* Throw error */ + +CREATE TABLE inhf (LIKE Inhx INCLUDING DEFAULTS INCLUDING CONSTRAINTS); +INSERT INTO inhf DEFAULT VALUES; +SELECT * FROM inhf; /* Single entry with value 'text' */ + +ALTER TABLE Inhx add constraint Foo CHECK (xx = 'text'); +ALTER TABLE Inhx ADD PRIMARY KEY (xx); +CREATE TABLE Inhg (LIKE Inhx); /* Doesn't copy constraint */ +INSERT INTO Inhg VALUES ('foo'); +DROP TABLE Inhg; +CREATE TABLE Inhg (x text, LIKE Inhx INCLUDING CONSTRAINTS, y text); /* Copies constraints */ +INSERT INTO Inhg VALUES ('x', 'text', 'y'); /* Succeeds */ +INSERT INTO Inhg VALUES ('x', 'text', 'y'); /* Succeeds -- Unique constraints not copied */ +INSERT INTO Inhg VALUES ('x', 'foo', 'y'); /* fails due to constraint */ +SELECT * FROM Inhg; /* Two records with three columns in order x=x, xx=text, y=y */ +DROP TABLE Inhg; + +CREATE TABLE Inhg (x text, LIKE Inhx INCLUDING INDEXES, y text) DISTRIBUTE BY REPLICATION; /* copies indexes */ +INSERT INTO Inhg VALUES (5, 10); +INSERT INTO Inhg VALUES (20, 10); -- should fail +DROP TABLE Inhg; +/* Multiple primary keys creation should fail */ +CREATE TABLE Inhg (x text, LIKE Inhx INCLUDING INDEXES, PRIMARY KEY(x)); /* fails */ +CREATE TABLE Inhz (xx text DEFAULT 'text', yy int UNIQUE) DISTRIBUTE BY REPLICATION; +CREATE UNIQUE INDEX Inhz_xx_idx on Inhz (xx) WHERE xx <> 'Test'; +/* Ok to create multiple unique indexes */ +CREATE TABLE Inhg (x text UNIQUE, LIKE Inhz INCLUDING INDEXES) DISTRIBUTE BY REPLICATION; +INSERT INTO Inhg (xx, yy, x) VALUES ('Test', 5, 10); +INSERT INTO Inhg (xx, yy, x) VALUES ('Test', 10, 15); +INSERT INTO Inhg (xx, yy, x) VALUES ('foo', 10, 15); -- should fail +DROP TABLE Inhg; +DROP TABLE Inhz; + +-- including storage and comments +CREATE TABLE Ctlt1 (a text CHECK (length(a) > 2) PRIMARY KEY, b text); +CREATE INDEX ctlt1_b_key ON Ctlt1 (b); +CREATE INDEX ctlt1_fnidx ON Ctlt1 ((a || b)); +COMMENT ON COLUMN Ctlt1.a IS 'A'; +COMMENT ON COLUMN Ctlt1.b IS 'B'; +COMMENT ON CONSTRAINT ctlt1_a_check ON Ctlt1 IS 't1_a_check'; +COMMENT ON INDEX ctlt1_pkey IS 'index pkey'; +COMMENT ON INDEX ctlt1_b_key IS 'index b_key'; +ALTER TABLE Ctlt1 ALTER COLUMN a SET STORAGE MAIN; + +CREATE TABLE Ctlt2 (c text); +ALTER TABLE Ctlt2 ALTER COLUMN c SET STORAGE EXTERNAL; +COMMENT ON COLUMN Ctlt2.c IS 'C'; + +CREATE TABLE Ctlt3 (a text CHECK (length(a) < 5), c text); +ALTER TABLE Ctlt3 ALTER COLUMN c SET STORAGE EXTERNAL; +ALTER TABLE Ctlt3 ALTER COLUMN a SET STORAGE MAIN; +COMMENT ON COLUMN Ctlt3.a IS 'A3'; +COMMENT ON COLUMN Ctlt3.c IS 'C'; +COMMENT ON CONSTRAINT ctlt3_a_check ON Ctlt3 IS 't3_a_check'; + +CREATE TABLE Ctlt4 (a text, c text); +ALTER TABLE Ctlt4 ALTER COLUMN c SET STORAGE EXTERNAL; + +CREATE TABLE Ctlt12_storage (LIKE Ctlt1 INCLUDING STORAGE, LIKE Ctlt2 INCLUDING STORAGE); +\d+ "Ctlt12_storage" +CREATE TABLE Ctlt12_comments (LIKE Ctlt1 INCLUDING COMMENTS, LIKE Ctlt2 INCLUDING COMMENTS); +\d+ "Ctlt12_comments" +CREATE TABLE Ctlt1_inh (LIKE Ctlt1 INCLUDING CONSTRAINTS INCLUDING COMMENTS) InheRITS (Ctlt1); +\d+ "Ctlt1_inh" +SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 'Ctlt1_inh'::regclass; +CREATE TABLE Ctlt13_inh () InheRITS (Ctlt1, Ctlt3); +\d+ "Ctlt13_inh" +CREATE TABLE ctlt13_like (LIKE Ctlt3 INCLUDING CONSTRAINTS INCLUDING COMMENTS INCLUDING STORAGE) InheRITS (Ctlt1); +\d+ "ctlt13_like" +SELECT description FROM pg_description, pg_constraint c WHERE classoid = 'pg_constraint'::regclass AND objoid = c.oid AND c.conrelid = 'ctlt13_like'::regclass; + +CREATE TABLE Ctlt_all (LIKE Ctlt1 INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS); +\d+ "Ctlt_all" +SELECT c.relname, objsubid, description FROM pg_description, pg_index i, pg_class c WHERE classoid = 'pg_class'::regclass AND objoid = i.indexrelid AND c.oid = i.indexrelid AND i.indrelid = 'Ctlt_all'::regclass ORDER BY c.relname, objsubid; + +CREATE TABLE Inh_error1 () InheRITS (Ctlt1, Ctlt4); +CREATE TABLE Inh_error2 (LIKE Ctlt4 INCLUDING STORAGE) InheRITS (Ctlt1); + +DROP TABLE if exists Ctlt1, Ctlt2, Ctlt3, Ctlt4, Ctlt12_storage, Ctlt12_comments, Ctlt1_inh, Ctlt13_inh, ctlt13_like, Ctlt_all, Ctla, Ctlb CASCADE; + + +/* LIKE with other relation kinds */ + +CREATE TABLE Ctlt4 (a int, b text); + +CREATE SEQUENCE ctlseq1; +CREATE TABLE ctlt10 (LIKE ctlseq1); -- fail + +CREATE VIEW ctlv1 AS SELECT * FROM Ctlt4; +CREATE TABLE Ctlt11 (LIKE ctlv1); +CREATE TABLE ctlt11a (LIKE ctlv1 INCLUDING DEFAULTS INCLUDING CONSTRAINTS INCLUDING INDEXES INCLUDING STORAGE INCLUDING COMMENTS); + +CREATE TYPE ctlty1 AS (a int, b text); +CREATE TABLE Ctlt12 (LIKE ctlty1); + +-- including all, including all excluding some option(s) +CREATE TABLE Ctlt13 (LIKE Ctlt4 INCLUDING ALL); +CREATE TABLE Ctlt14 (LIKE Ctlt4 INCLUDING ALL EXCLUDING RELOPTIONS) WITH (ORIENTATION = COLUMN); +-- should fail, syntax error +CREATE TABLE Ctlt15 (LIKE Ctlt4 INCLUDING ALL INCLUDING RELOPTIONS); +CREATE TABLE Ctlt16 (LIKE Ctlt4 INCLUDING ALL EXCLUDING ALL); +CREATE TABLE Ctlt17 (LIKE Ctlt4 INCLUDING DEFAULTS INCLUDING CONSTRAINTS EXCLUDING ALL); +CREATE TABLE Ctlt18 (LIKE Ctlt4 EXCLUDING ALL); + +DROP SEQUENCE ctlseq1; +DROP TYPE ctlty1; +DROP VIEW ctlv1; +DROP TABLE IF EXISTS Ctlt4, ctlt10, Ctlt11, ctlt11a, Ctlt12, Ctlt13, Ctlt14, Ctlt16, Ctlt17, Ctlt18; + +create table Ctltcol(id1 integer, id2 integer, id3 integer, partial cluster key(id1,id2))with(orientation = column); +create table Ctltcollike(like Ctltcol including all); +\d+ "Ctltcollike" +drop table Ctltcol; +drop table Ctltcollike; + +create table Test1(a int, b int, c int)distribute by hash(a, b); +create table Test (like Test1 including distribution); +\d+ "Test" +drop table Test; +drop table Test1; + +-- including all, with oids /without oids +create table Ctltesta(a1 int, a2 int) with oids; +\d+ "Ctltesta" +create table Ctltestb(like Ctltesta including all); +\d+ "Ctltestb" +create table Ctltestc(like Ctltesta including all excluding oids); +\d+ "Ctltestc" +create table Ctltestd(a1 int, a2 int, constraint firstkey primary key(a1))with oids distribute by hash(a1); +\d+ "Ctltestd" +create table Ctlteste(like Ctltestd including all); +\d+ "Ctlteste" +drop table if exists Ctltesta, Ctltestb, Ctltestc,Ctltestd, Ctlteste; +create table Ctltestf(a1 int, a2 int, constraint firstkey primary key(oid)) distribute by hash(a1); +\d+ "Ctltestf" +create table Ctltestg(a1 int, a2 int, constraint firstkey primary key(oid))with oids distribute by hash(a1); +\d+ "Ctltestg" +drop table if exists Ctltestf, Ctltestg; + +create schema testschema; +CREATE OR REPLACE FUNCTION testschema.func_increment_plsql(i integer) RETURNS integer AS $$ + BEGIN + RETURN i + 1; + END; +$$ LANGUAGE plpgsql IMMUTABLE ; +create table testschema.Test1 (a int , b int default testschema.func_increment_plsql(1)); +alter schema testschema rename to TESTTABLE_bak; +create table TESTTABLE_bak.Test2 (like TESTTABLE_bak.Test1 including all); + +drop table TESTTABLE_bak.Test2; +drop table TESTTABLE_bak.Test1; +drop function TESTTABLE_bak.func_increment_plsql(); diff --git a/contrib/dolphin/sql/case_sensitive_test/delete.sql b/contrib/dolphin/sql/case_sensitive_test/delete.sql new file mode 100644 index 0000000000000000000000000000000000000000..82e3c6712046a0e99620a5f8690a1cc7d6517507 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/delete.sql @@ -0,0 +1,27 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +CREATE TABLE Delete_test ( + id int PRIMARY KEY, + a INT, + b text +); + +INSERT INTO Delete_test (a) VALUES (10); +INSERT INTO Delete_test (a, b) VALUES (50, repeat('x', 10000)); +INSERT INTO Delete_test (a) VALUES (100); + +-- allow an alias to be specified for DELETE's target table +DELETE FROM Delete_test AS dt WHERE dt.a > 75; + +-- if an alias is specified, don't allow the original table name +-- to be referenced +DELETE FROM Delete_test dt WHERE Delete_test.a > 25; + +SELECT id, a, char_length(b) FROM Delete_test ORDER BY id; + +-- delete a row with a TOASTed value +DELETE FROM Delete_test WHERE a > 25; + +SELECT id, a, char_length(b) FROM Delete_test ORDER BY id; + +DROP TABLE Delete_test; diff --git a/contrib/dolphin/sql/case_sensitive_test/drop.sql b/contrib/dolphin/sql/case_sensitive_test/drop.sql new file mode 100644 index 0000000000000000000000000000000000000000..dc22f1698a1187ea5b7d52a4ce7e531af124b1f9 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/drop.sql @@ -0,0 +1,218 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- drop.source +-- + +-- +-- this will fail if the user is not the postgres superuser. +-- if it does, don't worry about it (you can turn usersuper +-- back on as "postgres"). too many people don't follow +-- directions and run this as "postgres", though... +-- +UPDATE pg_user + SET usesuper = 't'::bool + WHERE usename = 'postgres'; + + +-- +-- FUNCTION REMOVAL +-- +DROP FUNCTION hobbies("Person"); + +DROP FUNCTION hobby_construct(text,text); + +DROP FUNCTION equipment("Hobbies_r"); + +DROP FUNCTION user_relns(); + +DROP FUNCTION widget_in(cstring); + +DROP FUNCTION widget_out(widget); + +DROP FUNCTION pt_in_widget(point,widget); + +DROP FUNCTION overpaid(Emp); + +DROP FUNCTION boxarea(box); + +DROP FUNCTION interpt_pp(path,path); + +DROP FUNCTION reverse_name(name); + +DROP FUNCTION oldstyle_length(int4, text); + +-- +-- OPERATOR REMOVAL +-- +DROP OPERATOR ## (path, path); + +DROP OPERATOR <% (point, widget); + +-- left unary +DROP OPERATOR @#@ (none, int4); + +-- right unary +DROP OPERATOR #@# (int4, none); + +-- right unary +DROP OPERATOR #%# (int4, none); + + +-- +-- ABSTRACT DATA TYPE REMOVAL +-- +DROP TYPE city_budget; + +DROP TYPE widget; + + +-- +-- RULE REMOVAL +-- (is also tested in queries.source) +-- + +-- +-- AGGREGATE REMOVAL +-- +DROP AGGREGATE newavg (int4); + +DROP AGGREGATE newsum (int4); + +DROP AGGREGATE newcnt (int4); + + +-- +-- CLASS REMOVAL +-- (Inheritance hierarchies are deleted in reverse order) +-- + +-- +-- DROP ancillary data structures (i.e. indices) +-- +DROP INDEX onek_unique1; + +DROP INDEX onek_unique2; + +DROP INDEX onek_hundred; + +DROP INDEX onek_stringu1; + +DROP INDEX tenk1_unique1; + +DROP INDEX tenk1_unique2; + +DROP INDEX tenk1_hundred; + +DROP INDEX tenk2_unique1; + +DROP INDEX tenk2_unique2; + +DROP INDEX tenk2_hundred; + +-- DROP INDEX onek2_u1_prtl; + +-- DROP INDEX onek2_u2_prtl; + +-- DROP INDEX onek2_stu1_prtl; + +DROP INDEX rix; + +DROP INDEX iix; + +DROP INDEX six; + +DROP INDEX hash_i4_index; + +DROP INDEX hash_name_index; + +DROP INDEX hash_txt_index; + +DROP INDEX hash_f8_index; + +-- DROP INDEX hash_ovfl_index; + +DROP INDEX bt_i4_index; + +DROP INDEX bt_name_index; + +DROP INDEX bt_txt_index; + +DROP INDEX bt_f8_index; + + +DROP TABLE Onek; + +DROP TABLE Onek2; + +DROP TABLE Tenk1; + +DROP TABLE Tenk2; + +DROP TABLE Hobbies_r; + +DROP TABLE Equipment_r; + +DROP TABLE AggTest; + +DROP TABLE f_Star; + +DROP TABLE e_Star; + +DROP TABLE d_Star; + +DROP TABLE c_Star; + +DROP TABLE b_Star; + +DROP TABLE a_Star; + + +-- +-- must be in reverse Inheritance order +-- +DROP TABLE Stud_Emp; + +DROP TABLE Student; + +DROP TABLE Slow_emp4000; + +DROP TABLE Fast_emp4000; + +DROP TABLE Emp; + +DROP TABLE Person; + + +DROP TABLE ramp; + +DROP TABLE Real_City; + +DROP TABLE Dept; + +DROP TABLE iHighway; + +DROP TABLE sHighway; + +DROP TABLE Road; + +DROP TABLE City; + + +DROP TABLE Hash_i4_heap; + +DROP TABLE Hash_name_heap; + +DROP TABLE Hash_txt_heap; + +DROP TABLE Hash_f8_heap; + +-- DROP TABLE hash_ovfl_heap; + +DROP TABLE BT_i4_heap; + +DROP TABLE BT_name_heap; + +DROP TABLE BT_txt_heap; + +DROP TABLE BT_f8_heap; diff --git a/contrib/dolphin/sql/case_sensitive_test/insert.sql b/contrib/dolphin/sql/case_sensitive_test/insert.sql new file mode 100644 index 0000000000000000000000000000000000000000..72bb32988424e46dbf467a24fed4d5f4e0b754b8 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/insert.sql @@ -0,0 +1,68 @@ +\c table_name_test_db;te_test +SET lower_case_table_names TO 0; +-- +-- insert with DEFAULT in the target_list +-- +create table Inserttest (col1 int4, col2 int4 NOT NULL, col3 text default 'testing'); +insert into Inserttest (col1, col2, col3) values (DEFAULT, DEFAULT, DEFAULT); +insert into Inserttest (col2, col3) values (3, DEFAULT); +insert into Inserttest (col1, col2, col3) values (DEFAULT, 5, DEFAULT); +insert into Inserttest values (DEFAULT, 5, 'test'); +insert into Inserttest values (DEFAULT, 7); + +select * from Inserttest; + +-- +-- insert with similar expression / target_list values (all fail) +-- +insert into Inserttest (col1, col2, col3) values (DEFAULT, DEFAULT); +insert into Inserttest (col1, col2, col3) values (1, 2); +insert into Inserttest (col1) values (1, 2); +insert into Inserttest (col1) values (DEFAULT, DEFAULT); + +select * from Inserttest; + +-- +-- VALUES test +-- +insert into Inserttest values(10, 20, '40'), (-1, 2, DEFAULT), + ((select 2), (select i from (values(3)) as foo (i)), 'values are fun!'); + +select * from Inserttest order by 1,2,3; + +-- +-- TOASTed value test +-- +insert into Inserttest values(30, 50, repeat('x', 10000)); + +select col1, col2, char_length(col3) from Inserttest order by 1,2,3; + +drop table Inserttest; + +-- +---- I tried to use generate_series() function to load a bunch of test data in a +---- table. It fails with the following error: +---- set-valued function called in context that cannot accept a set +-- +-- distribute by hash +create table Test_hash(a int, b char(10)); +insert into Test_hash values (generate_series(1,1000), 'foo'); +drop table Test_hash; + +-- distribute by modulo +create table Test_modulo(a int, b char(10)); +insert into Test_modulo values (generate_series(1,1000), 'foo'); +drop table Test_modulo; + +-- distribute by replication +create table Test_replication(a int, b char(10)); +insert into Test_replication values (generate_series(1,1000), 'foo'); +drop table Test_replication; + +-- distribute by roundrobin +create table Test_roundrobin(a int, b char(10)); +insert into Test_roundrobin values (generate_series(1,1000), 'foo'); +drop table Test_roundrobin; + +--insert into pg_auth_history +insert into pg_auth_history values(10, '2015-110-10 08:00:00.57603+08', 'sha256232f8630ce6af1095f6db3ed4c05a48747038936d42176e1103594d43c7d1adc4aca54361a23e51c6cd9371ccc95776450219376e45bcca01e27a7f06bf8088a8b1a9e280cdcc315c8134879818442bc3e92064a70e27b2ea83fcf6990a607d0'); diff --git a/contrib/dolphin/sql/case_sensitive_test/reindex_internal.sql b/contrib/dolphin/sql/case_sensitive_test/reindex_internal.sql new file mode 100644 index 0000000000000000000000000000000000000000..82b2b84192bcd7757763ec66666850327791ecad --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/reindex_internal.sql @@ -0,0 +1,265 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +--REINDEX INTERNAL TABLE name [PARTITION name]: +-- used to reindex the index of the cudesc table. + + +drop schema if exists reindexinternal cascade; +create schema reindexinternal; +set current_schema = reindexinternal; +set max_query_retry_times = 3; + +--case1 reindex internal table col_tb; +drop table if exists T1; +create table T1(a int, b int)with (orientation=column); +insert into T1 values (1,1); +insert into T1 values (1,2); +insert into T1 values (2,1); + +create index a_idx_t1 on T1 using btree(a); +reindex index a_idx_t1; +reindex table T1; +reindex internal table T1; + +--case2 reindex internal table col_part_tb; +drop table if exists T2; +create table T2( + c_id varchar, + c_w_id integer, + c_date date, + partial cluster key(c_id,c_w_id) + ) with (orientation=column,max_batchrow= 30700, compression = middle) +partition by range (c_date,c_w_id) +( + PARTITION t2_1 values less than ('20170331',5), + PARTITION t2_2 values less than ('20170731',450), + PARTITION t2_3 values less than ('20170930',1062), + PARTITION t2_4 values less than ('20171231',1765), + PARTITION t2_5 values less than ('20180331',2024), + PARTITION t2_6 values less than ('20180731',2384), + PARTITION t2_7 values less than ('20180930',2786), + PARTITION t2_8 values less than (maxvalue,maxvalue) +); + +insert into T2 values('gauss1',4,'20170301'); +insert into T2 values('gauss2',400,'20170625'); +insert into T2 values('gauss3',480,'20170920'); +insert into T2 values('gauss4',1065,'20170920'); +insert into T2 values('gauss5',1800,'20170920'); +insert into T2 values('gauss6',2030,'20170920'); +insert into T2 values('gauss7',2385,'20170920'); +insert into T2 values('gauss8',2789,'20191020'); +insert into T2 values('gauss9',2789,'20171020'); + +create index idx_t2 on T2 using btree(c_id) LOCAL; +create index idx2_t2 on T2 using btree(c_id) LOCAL ( + PARTITION t2_1_index, + PARTITION t2_2_index, + PARTITION t2_3_index, + PARTITION t2_4_index, + PARTITION t2_5_index, + PARTITION t2_6_index, + PARTITION t2_7_index, + PARTITION t2_8_index +); +reindex index idx_t2; +reindex index idx2_t2 partition t2_1_index; +reindex table T2; +reindex internal table T2; +reindex table T2 partition t2_1; +reindex internal table T2 partition t2_1; + + +--case3 reindex internal table col_part_tb partition part_name; +drop table if exists T3; +CREATE TABLE T3( +CA_ADDRESS_SK INTEGER NOT NULL, +CA_ADDRESS_ID CHAR(16) NOT NULL, +CA_STREET_NUMBER CHAR(10) , +CA_STREET_NAME VARCHAR(60) , +CA_STREET_TYPE CHAR(15) , +CA_SUITE_NUMBER CHAR(10) , +CA_CITY VARCHAR(60) , +CA_COUNTY VARCHAR(30) , +CA_STATE CHAR(2) , +CA_ZIP CHAR(10) , +CA_COUNTRY VARCHAR(20) , +CA_GMT_OFFSET DECIMAL(5,2) , +CA_LOCATION_TYPE CHAR(20) +)with (orientation=column,max_batchrow= 30700, compression = middle) +PARTITION BY RANGE(CA_ADDRESS_SK) +( PARTITION t3_1 VALUES LESS THAN (3000), + PARTITION t3_2 VALUES LESS THAN (5000), + PARTITION t3_3 VALUES LESS THAN (MAXVALUE) +)ENABLE ROW MOVEMENT; + +CREATE INDEX t3_idx ON T3(CA_ADDRESS_SK) LOCAL; + +CREATE INDEX t3_idx2 ON T3(CA_ADDRESS_SK) LOCAL( + PARTITION CA_ADDRESS_SK_index1, + PARTITION CA_ADDRESS_SK_index2, + PARTITION CA_ADDRESS_SK_index3 +); + +reindex index t3_idx2 partition CA_ADDRESS_SK_index1; +reindex table T3 partition t3_1; +reindex internal table T3 partition t3_2; + +--case4 reindex internal table col_rep_tb partition part_name; +drop table if exists T4; +create table T4( + c_id varchar, + c_w_id integer, + c_date date, + partial cluster key(c_id,c_w_id) + ) with (orientation=column,max_batchrow= 30700, compression = middle) +partition by range (c_date,c_w_id) +( + PARTITION t4_1 values less than ('20170331',5), + PARTITION t4_2 values less than ('20170731',450), + PARTITION t4_3 values less than ('20170930',1062), + PARTITION t4_4 values less than ('20171231',1765), + PARTITION t4_5 values less than ('20180331',2024), + PARTITION t4_6 values less than ('20180731',2384), + PARTITION t4_7 values less than ('20180930',2786), + PARTITION t4_8 values less than (maxvalue,maxvalue) +); + +insert into T4 values('gauss1',4,'20170301'); +insert into T4 values('gauss2',400,'20170625'); +insert into T4 values('gauss3',480,'20170920'); +insert into T4 values('gauss4',1065,'20170920'); +insert into T4 values('gauss5',1800,'20170920'); +insert into T4 values('gauss6',2030,'20170920'); +insert into T4 values('gauss7',2385,'20170920'); +insert into T4 values('gauss8',2789,'20191020'); +insert into T4 values('gauss9',2789,'20171020'); + +create index a_idx_t4 on T4 using btree(c_id) LOCAL; +reindex index a_idx_t4; +reindex table T4; +reindex internal table T4; +reindex table T4 partition t4_1; +reindex internal table T4 partition t4_1; + +--case5 reindex internal table temp_tb; +drop table if exists T5; +create temp table T5(a int, b int)with (orientation=column); +insert into T5 values (1,1); +insert into T5 values (1,2); +insert into T5 values (2,1); + +create index a_idx_t5 on T5 using btree(a); +reindex index a_idx_t5; +reindex table T5; +reindex internal table T5; + +--case6 reindex internal table unlog_tb; +drop table if exists T6; +create unlogged table T6 +( +c_int int, +c_tinyint tinyint, +c_smallint smallint, +c_integer integer, +c_bigint bigint, +c_numeric numeric, +c_decimal decimal, +c_real real, +c_float4 float4, +c_float8 float8, +c_double1 double precision, +c_double2 binary_double, +c_char1 char(100), +c_char2 character(100), +c_char3 nchar(100), +c_char4 varchar(100), +c_char5 character varying(100), +c_char6 nvarchar2(100), +c_char7 varchar2(100), +c_clob text, +c_text text, +c_date date, +c_time1 time with time zone, +c_time2 time without time zone, +c_timestamp1 timestamp with time zone, +c_timestamp2 timestamp without time zone, +c_smalldatetime smalldatetime, +c_interval interval, +c_boolean boolean, +c_oid oid, +c_money money +)with(orientation=column); + +create index a_idx_t6 on T6 using btree(a); +reindex index a_idx_t6; +reindex table T6; +reindex internal table T6; + +--case7 reindex internal table row_tb; +drop table if exists T7; +create table T7(a int, b int); +insert into T7 values (1,1); +insert into T7 values (1,2); +insert into T7 values (2,1); + +create index a_idx_t7 on T7 (a); +reindex index a_idx_t7; +reindex table T7; +reindex internal table T7; + +--case8 reindex单个并发执行+并发分区表+并发分区表的分区+混合并发; +\parallel on +reindex internal table T1; +reindex internal table T1; +reindex internal table T1; +reindex internal table T1; +reindex internal table T1; +\parallel off + +\parallel on +reindex internal table T2; +reindex internal table T2; +reindex internal table T2; +reindex internal table T2; +reindex internal table T2; +\parallel off + +\parallel on +reindex internal table T2 partition t2_2; +reindex internal table T2 partition t2_3; +reindex internal table T2 partition t2_1; +reindex internal table T2 partition t2_8; +reindex internal table T2 partition t2_5; +reindex internal table T2 partition t2_4; +reindex internal table T2 partition t2_6; +reindex internal table T2 partition t2_7; +\parallel off + + +\parallel on +reindex internal table T3 partition t3_2; +reindex internal table T3 partition t3_2; +reindex internal table T3 partition t3_2; +reindex internal table T3 partition t3_2; +reindex internal table T3 partition t3_2; +\parallel off + + + +\parallel on +reindex internal table T1; +reindex internal table T3 partition t3_3; +reindex internal table T2; +reindex internal table T3; +reindex internal table T3 partition t3_1; +\parallel off + +drop table T1; +drop table T2; +drop table T3; +drop table T4; +drop table T5; +drop table T6; +drop table T7; +drop schema reindexinternal cascade; \ No newline at end of file diff --git a/contrib/dolphin/sql/case_sensitive_test/role_test.sql b/contrib/dolphin/sql/case_sensitive_test/role_test.sql new file mode 100644 index 0000000000000000000000000000000000000000..816ca37217d449900f64e2b9d2a02029a4e56c05 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/role_test.sql @@ -0,0 +1,26 @@ +DROP DATABASE IF EXISTS role_test_db; +CREATE DATABASE role_test_db dbcompatibility 'b'; +\c role_test_db; +SET lower_case_table_names TO 0; +CREATE TABLE test_table (a int); +CREATE USER Test_User WITH PASSWORD 'openGauss@123'; +SELECT rolname FROM pg_roles WHERE rolname LIKE '%Test_%'; +GRANT ALL PRIVILEGES TO test_user; +REVOKE ALL PRIVILEGES FROM test_user; +GRANT ALL PRIVILEGES TO Test_User; +REVOKE ALL PRIVILEGES FROM Test_User; + +ALTER USER test_user RENAME TO test_USer; +ALTER USER Test_User RENAME TO test_USer; + +CREATE SCHEMA test_scheam AUTHORIZATION test_user; +CREATE SCHEMA test_scheam AUTHORIZATION test_USer; + +ALTER TABLE test_table OWNER TO test_user; +ALTER TABLE test_table OWNER TO test_USer; + +DROP USER test_user CASCADE; +DROP USER test_USer CASCADE; + +\c postgres +DROP DATABASE role_test_db; \ No newline at end of file diff --git a/contrib/dolphin/sql/case_sensitive_test/rowlevelsecurity.sql b/contrib/dolphin/sql/case_sensitive_test/rowlevelsecurity.sql new file mode 100644 index 0000000000000000000000000000000000000000..7faf28fea5f32d4b21a0bc8bdb7cefc46ebe6b61 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/rowlevelsecurity.sql @@ -0,0 +1,432 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- Test for Row Level Security feature +-- +-- initial setup +CREATE USER regress_rls_alice NOLOGIN PASSWORD 'Ttest@123'; +CREATE USER regress_rls_bob NOLOGIN PASSWORD 'Ttest@123'; +CREATE USER regress_rls_david NOLOGIN PASSWORD 'Ttest@123'; +CREATE USER regress_rls_peter NOLOGIN PASSWORD 'Ttest@123'; +CREATE USER regress_rls_single_user NOLOGIN PASSWORD 'Ttest@123'; +CREATE USER regress_rls_admin SYSADMIN NOLOGIN PASSWORD "Ttest@123"; +CREATE ROLE regress_rls_group1 NOLOGIN PASSWORD 'Ttest@123'; +CREATE ROLE regress_rls_group2 NOLOGIN PASSWORD 'Ttest@123'; +GRANT ALL on pg_roles to public; +GRANT ALL on pg_user to public; +GRANT regress_rls_group1 TO regress_rls_alice, regress_rls_bob, regress_rls_peter; +GRANT regress_rls_group2 TO regress_rls_david, regress_rls_peter, regress_rls_admin; + +CREATE SCHEMA regress_rls_schema; +GRANT CREATE ON SCHEMA regress_rls_schema to public; +GRANT USAGE ON SCHEMA regress_rls_schema to public; +ALTER DATABASE regression ENABLE PRIVATE OBJECT; +-- reconnect +\c +SET search_path = regress_rls_schema; +-- regress_rls_alice is the owner of all schema +SET ROLE regress_rls_alice PASSWORD 'Ttest@123'; +-- setup of malicious function (NOT SHIPPABLE) +CREATE OR REPLACE FUNCTION regress_rls_schema.rls_fleak1(text) RETURNS bool + COST 0.0000001 LANGUAGE plpgsql + AS 'BEGIN RAISE NOTICE ''f_leak => %'', $1; RETURN true; END'; +GRANT EXECUTE ON FUNCTION regress_rls_schema.rls_fleak1(text) TO public; + +-- setup of malicious immutable function (SHIPPABLE) +CREATE OR REPLACE FUNCTION regress_rls_schema.rls_fleak2(text) RETURNS bool + COST 0.0000001 LANGUAGE plpgsql IMMUTABLE + AS 'BEGIN RAISE NOTICE ''f_leak => %'', $1; RETURN true; END'; +GRANT EXECUTE ON FUNCTION regress_rls_schema.rls_fleak2(text) TO public; + +-- auto generate row level security policy +CREATE OR REPLACE FUNCTION regress_rls_schema.rls_auto_create_policy(t_name text, p_num int) +RETURNS INTEGER AS $$ +DECLARE + counter INTEGER := 1; + query text; +BEGIN + WHILE counter <= p_num LOOP + query := 'CREATE ROW LEVEL SECURITY POLICY ' || t_name || '_rls_' || counter || ' ON ' || t_name || ' USING(TRUE);'; + EXECUTE query; + counter := counter + 1; + END LOOP; + RETURN 1; +END; +$$language plpgsql; +REVOKE EXECUTE ON FUNCTION regress_rls_schema.rls_auto_create_policy(text, int) FROM public; + +-- auto drop row level security policy +CREATE OR REPLACE FUNCTION regress_rls_schema.rls_auto_drop_policy(t_name text, p_num int) RETURNS INTEGER AS $$ +DECLARE + counter INTEGER := 1; + query text; +BEGIN + WHILE counter <= p_num LOOP + query := 'DROP ROW LEVEL SECURITY POLICY ' || t_name || '_rls_' || counter || ' ON ' || t_name; + EXECUTE query; + counter := counter + 1; + END LOOP; + RETURN 1; +END; +$$language plpgsql; +REVOKE EXECUTE ON FUNCTION regress_rls_schema.rls_auto_drop_policy(text, int) FROM public; + +-- BASIC Row-Level Security Scenario +CREATE TABLE regress_rls_schema.account_row( + aid int, + aname varchar(100) +) WITH (ORIENTATION=row); +GRANT SELECT ON regress_rls_schema.account_row TO public; +INSERT INTO regress_rls_schema.account_row VALUES + (1, 'regress_rls_alice'), + (2, 'regress_rls_bob'), + (3, 'regress_rls_david'), + (4, 'regress_rls_peter'), + (5, 'regress_rls_admin'), + (6, 'regress_rls_single_user'); +ANALYZE regress_rls_schema.account_row; + +CREATE TABLE regress_rls_schema.account_col( + aid int, + aname varchar(100) +) WITH (ORIENTATION=column); +GRANT SELECT ON regress_rls_schema.account_col TO public; +INSERT INTO regress_rls_schema.account_col SELECT * FROM regress_rls_schema.account_row; +ANALYZE regress_rls_schema.account_col; + +CREATE TABLE regress_rls_schema.category_row( + cid int primary key, + cname text +) WITH (ORIENTATION=row); +GRANT ALL ON regress_rls_schema.category_row TO public; +INSERT INTO regress_rls_schema.category_row VALUES + (11, 'novel'), + (22, 'science fiction'), + (33, 'technology'), + (44, 'manga'), + (55, 'biography'); +ANALYZE regress_rls_schema.category_row; + +CREATE TABLE regress_rls_schema.category_col( + cid int, + cname text +) WITH (ORIENTATION=column); +GRANT ALL ON regress_rls_schema.category_col TO public; +INSERT INTO regress_rls_schema.category_col SELECT * FROM regress_rls_schema.category_row; +ANALYZE regress_rls_schema.category_col; + +CREATE TABLE regress_rls_schema.document_row( + did int primary key, + cid int, + dlevel int not null, + dauthor name, + dtitle text +); +GRANT ALL ON regress_rls_schema.document_row TO public; +INSERT INTO regress_rls_schema.document_row VALUES + ( 1, 11, 1, 'regress_rls_bob', 'my first novel'), + ( 2, 11, 5, 'regress_rls_bob', 'my second novel'), + ( 3, 22, 7, 'regress_rls_bob', 'my science fiction'), + ( 4, 44, 9, 'regress_rls_bob', 'my first manga'), + ( 5, 44, 3, 'regress_rls_bob', 'my second manga'), + ( 6, 22, 2, 'regress_rls_peter', 'great science fiction'), + ( 7, 33, 6, 'regress_rls_peter', 'great technology book'), + ( 8, 44, 4, 'regress_rls_peter', 'great manga'), + ( 9, 22, 5, 'regress_rls_david', 'awesome science fiction'), + (10, 33, 4, 'regress_rls_david', 'awesome technology book'), + (11, 55, 8, 'regress_rls_alice', 'great biography'), + (12, 33, 10, 'regress_rls_admin', 'physical technology'), + (13, 55, 5, 'regress_rls_single_user', 'Beethoven biography'); +ANALYZE regress_rls_schema.document_row; + +CREATE TABLE regress_rls_schema.document_col( + did int, + cid int, + dlevel int not null, + dauthor name, + dtitle text +); +GRANT ALL ON regress_rls_schema.document_col TO public; +INSERT INTO regress_rls_schema.document_col SELECT * FROM regress_rls_schema.document_row; +ANALYZE regress_rls_schema.document_col; + +-- create partition table +CREATE TABLE par_row_t1 (id int, a int, b text)partition by range (a) +( + partition par_row_t1_p0 values less than(10), + partition par_row_t1_p1 values less than(50), + partition par_row_t1_p2 values less than(100), + partition par_row_t1_p3 values less than (maxvalue) +); + +CREATE TABLE par_col_t1(id int, a int, b text) with(orientation = column) /*distribute by hash (id)*/ PARTITION BY RANGE (a) +( + partition par_col_t1_p0 values less than(10), + partition par_col_t1_p1 values less than(50), + partition par_col_t1_p2 values less than(100), + partition par_col_t1_p3 values less than (maxvalue) +); + +INSERT INTO par_row_t1 VALUES (generate_series(1, 150) % 24, generate_series(1, 150), 'huawei'); +INSERT INTO par_col_t1 VALUES (generate_series(1, 150) % 24, generate_series(1, 150), 'huawei'); + +GRANT SELECT ON par_row_t1 TO PUBLIC; +GRANT SELECT ON par_col_t1 TO PUBLIC; + +CREATE ROW LEVEL SECURITY POLICY par_row_t1_rls1 ON par_row_t1 AS PERMISSIVE TO public USING(a <= 20); +CREATE ROW LEVEL SECURITY POLICY par_row_t1_rls2 ON par_row_t1 AS RESTRICTIVE TO regress_rls_group2 USING(id < 30); +CREATE ROW LEVEL SECURITY POLICY par_col_t1_rls1 ON par_col_t1 AS PERMISSIVE TO public USING(a <= 20); +CREATE ROW LEVEL SECURITY POLICY par_col_t1_rls2 ON par_col_t1 AS RESTRICTIVE TO regress_rls_group2 USING(id < 30); + +ALTER TABLE par_row_t1 ENABLE ROW LEVEL SECURITY; +ALTER TABLE par_col_t1 ENABLE ROW LEVEL SECURITY; + +-- create replication table +CREATE TABLE tt_rep(id int, name varchar(100)) /*DISTRIBUTE BY REPLICATION*/; +GRANT SELECT ON tt_rep TO PUBLIC; +INSERT INTO tt_rep VALUES (1, 'regress_rls_alice'), (2, 'regress_rls_david'), (3, 'regress_rls_peter'), (4, 'regress_rls_bob'); +ALTER TABLE tt_rep ENABLE ROW LEVEL SECURITY; +CREATE ROW LEVEL SECURITY POLICY tt_rep_rls1 ON tt_rep AS PERMISSIVE FOR SELECT TO regress_rls_group1 USING(name = current_user); +CREATE ROW LEVEL SECURITY POLICY tt_rep_rls2 ON tt_rep AS PERMISSIVE FOR SELECT TO regress_rls_group2 USING(id = 1); + +-- create private table, test database private object +CREATE TABLE alice_private(id int, name varchar(100)); +CREATE TABLE alice_public_1(id int, name varchar(100)); +GRANT SELECT ON alice_public_1 TO regress_rls_group1; +CREATE TABLE alice_public_2(id int, name varchar(100)); +GRANT SELECT ON alice_public_2 TO regress_rls_group2; + +-- create temp table +CREATE TEMP TABLE temp_tt(id int, name varchar(20)); +CREATE ROW LEVEL SECURITY POLICY temp_tt_rls ON temp_tt USING(id < 100); +ALTER TABLE temp_tt ENABLE ROW LEVEL SECURITY; +DROP TABLE temp_tt; + +-- create 100 row level security policies on account_row +SELECT regress_rls_schema.rls_auto_create_policy('account_row', 100); +-- create 101 row level security policy on account_row, failed +CREATE ROW LEVEL SECURITY POLICY account_row_rls_101 ON regress_rls_schema.account_row USING(FALSE); +-- drop 100 row level security policies on account_row +SELECT regress_rls_schema.rls_auto_drop_policy('account_row', 100); +-- create row level security policy on account_row, succeed +CREATE ROW LEVEL SECURITY POLICY account_row_rls_101 ON regress_rls_schema.account_row USING(FALSE); +-- drop row level security policy account_row_rls_101 for account_row +DROP ROW LEVEL SECURITY POLICY account_row_rls_101 ON regress_rls_schema.account_row; +SELECT count(*) FROM pg_catalog.pg_rlspolicies where tablename = 'account_row'; + +-- enable row level security for document_row, document_col +ALTER TABLE regress_rls_schema.document_row ENABLE ROW LEVEL SECURITY; +ALTER TABLE regress_rls_schema.document_col ENABLE ROW LEVEL SECURITY; +-- user's security level must be higher than or equal to document's +CREATE ROW LEVEL SECURITY POLICY p01 ON document_row AS PERMISSIVE + USING (dlevel <= (SELECT aid FROM account_row WHERE aname = current_user)); +CREATE ROW LEVEL SECURITY POLICY p01 ON document_col AS PERMISSIVE + USING (dlevel <= (SELECT aid FROM account_col WHERE aname = current_user)); + +-- try to create a policy of wrong type +CREATE ROW LEVEL SECURITY POLICY p02 ON document_row AS WHATEVER + USING (dlevel <= (SELECT aid FROM account_row WHERE aname = current_user)); + +-- regress_rls_david isn't allowed to anything at cid 50 or above +-- this is to make sure that we sort the policies by name first +CREATE ROW LEVEL SECURITY POLICY p02 ON document_row AS RESTRICTIVE TO regress_rls_david + USING (cid < 50); +CREATE ROW LEVEL SECURITY POLICY p02 ON document_col AS RESTRICTIVE TO regress_rls_david + USING (cid < 50); + +-- and regress_rls_david isn't allowed to see manga documents +CREATE ROW LEVEL SECURITY POLICY p03 ON document_row AS RESTRICTIVE TO regress_rls_david + USING (cid <> 44); +CREATE ROW LEVEL SECURITY POLICY p03 ON document_col AS RESTRICTIVE TO regress_rls_david + USING (cid <> 44); + +-- policy for update/delete +CREATE ROW LEVEL SECURITY POLICY p04 ON document_row AS RESTRICTIVE FOR UPDATE TO regress_rls_bob, regress_rls_david USING ((dlevel % 2) = 1); +CREATE ROW LEVEL SECURITY POLICY p05 ON document_row AS RESTRICTIVE FOR DELETE TO regress_rls_bob, regress_rls_david USING ((dlevel % 2) = 0); + +-- policy for regress_rls_bob +CREATE ROW LEVEL SECURITY POLICY p06 ON document_row AS RESTRICTIVE FOR SELECT TO regress_rls_bob USING ((dlevel % 2) = 1); + +\d +\d+ "document_row" +SELECT * FROM pg_rlspolicies WHERE schemaname = 'regress_rls_schema' AND tablename = 'document_row' ORDER BY policyname; +-- prepare statement +PREPARE one AS SELECT * FROM document_row ORDER BY 1; +PREPARE two AS SELECT * FROM document_col ORDER BY 1; +EXECUTE one; +EXECUTE one; +EXECUTE two; +EXECUTE two; + +-- viewpoint from regress_rls_bob +SET ROLE regress_rls_bob PASSWORD 'Ttest@123'; +EXECUTE one; +EXECUTE two; +SELECT * FROM document_row WHERE rls_fleak1(dtitle) ORDER BY did; +SELECT * FROM document_col WHERE rls_fleak2(dauthor) ORDER BY did; +-- EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row WHERE rls_fleak2(dauthor) ORDER BY did; +SELECT * FROM document_col INNER JOIN category_col ON document_col.cid=category_col.cid WHERE rls_fleak1(dtitle) ORDER BY did; +SELECT * FROM tt_rep; +SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; +-- EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; +\d +\df +-- viewpoint from regress_rls_peter +SET ROLE regress_rls_peter PASSWORD 'Ttest@123'; +EXECUTE one; +EXECUTE two; +SELECT * FROM document_row WHERE rls_fleak1(dtitle) ORDER BY did; +SELECT * FROM document_col WHERE rls_fleak2(dauthor) ORDER BY did; +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row WHERE rls_fleak2(dauthor) ORDER BY did; +SELECT * FROM document_col INNER JOIN category_col ON document_col.cid=category_col.cid WHERE rls_fleak1(dtitle) ORDER BY did; +SELECT * FROM tt_rep; +SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; + +-- viewpoint from regress_rls_david +SET ROLE regress_rls_david PASSWORD 'Ttest@123'; +EXECUTE one; +EXECUTE two; +SELECT * FROM document_row WHERE rls_fleak1(dtitle) ORDER BY did; +SELECT * FROM document_col WHERE rls_fleak2(dauthor) ORDER BY did; +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row ORDER BY did; +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row WHERE rls_fleak2(dauthor) ORDER BY did; +SELECT * FROM document_col INNER JOIN category_col ON document_col.cid=category_col.cid WHERE rls_fleak1(dtitle) ORDER BY did; +SELECT * FROM tt_rep; +COPY document_row TO STDOUT; +COPY document_col TO STDOUT; +SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dauthor) ORDER BY did; + +-- update and update returning +UPDATE document_row SET dlevel = dlevel + 1 - 1 WHERE did > 1; +UPDATE document_col SET dlevel = dlevel + 1 - 1 WHERE did > 1 RETURNING dauthor, did; + +-- delete and delete returning +INSERT INTO document_row VALUES (100, 49, 1, 'regress_rls_david', 'testing sorting of policies'); +DELETE FROM document_row WHERE did = 100; +INSERT INTO document_row VALUES (100, 49, 1, 'regress_rls_david', 'testing sorting of policies'); +DELETE FROM document_row WHERE did = 100 RETURNING dauthor, did; + +-- only owner can change policies +ALTER POLICY p01 ON document_row USING (true); --fail +DROP POLICY p01 ON document_col; --fail + +-- check data from partition table +SELECT * FROM par_row_t1 WHERE a > 7 ORDER BY 1, 2; +SELECT * FROM par_col_t1 WHERE a > 7 ORDER BY 1, 2; + +-- test create table as +CREATE TABLE document_row_david AS SELECT * FROM document_row; +SELECT COUNT(*) FROM document_row_david; + +-- check table and functions +\d +\df + +-- change to super user +RESET ROLE; +-- DROP USER failed, display dependency +DROP USER regress_rls_bob; +DROP OWNED BY regress_rls_bob; +select * from pg_shdepend where classid = 3254 and refclassid = 1260 and refobjid = (select oid from pg_authid where rolname = 'regress_rls_bob'); +DROP USER regress_rls_bob; +ALTER POLICY p01 ON document_row USING (dauthor = current_user); +ALTER POLICY p01 ON document_row RENAME TO p12; +ALTER POLICY p12 ON document_row RENAME TO p13; +ALTER POLICY p13 ON document_row RENAME TO p01; +SELECT * FROM pg_rlspolicies ORDER BY tablename, policyname; +-- enable private object +ALTER DATABASE regression DISABLE PRIVATE OBJECT; +-- reconnect +\c +SET search_path = regress_rls_schema; +-- check audit logs +SELECT type, database, object_name, detail_info FROM pg_query_audit('2000-01-01 00:00:00', '2100-01-01 00:00:00') + WHERE detail_info LIKE '%private object%' OR detail_info LIKE '%PRIVATE OBJECT%' ORDER BY detail_info; + +-- viewpoint from rls_regres_david again +SET ROLE regress_rls_david PASSWORD 'Ttest@123'; +SELECT * FROM document_row ORDER BY did; +SELECT * FROM document_col ORDER BY did; +SELECT * FROM document_row WHERE rls_fleak1(dtitle) ORDER BY did; +SELECT * FROM document_row WHERE rls_fleak2(dtitle) ORDER BY did; +EXPLAIN (COSTS OFF, VERBOSE ON) SELECT * FROM document_row WHERE rls_fleak2(dtitle); +SELECT * FROM document_row INNER JOIN category_row ON document_row.cid=category_row.cid WHERE rls_fleak2(dtitle) ORDER by did; +-- test inlist +SET qrw_inlist2join_optmode=1; +CREATE TABLE inlist_t1(c1 int, c2 int, c3 int) /*DISTRIBUTE BY HASH(c1)*/; +INSERT INTO inlist_t1 SELECT v,v,v FROM generate_series(1,12) as v; +CREATE ROW LEVEL SECURITY POLICY inlist_t1_rls ON inlist_t1 USING(c3 IN (3,4,7)); +ALTER TABLE inlist_t1 ENABLE ROW LEVEL SECURITY; +ALTER TABLE inlist_t1 FORCE ROW LEVEL SECURITY; +SELECT * FROM inlist_t1 ORDER BY c1; +RESET qrw_inlist2join_optmode; +-- check data from partition table +SELECT * FROM par_row_t1 WHERE a > 7 ORDER BY 1, 2; +SELECT * FROM par_col_t1 WHERE a > 7 ORDER BY 1, 2; +SELECT * FROM tt_rep; +-- check table and functions +\d +\df + +-- viewpoint from regress_rls_alice again +SET ROLE regress_rls_alice PASSWORD 'Ttest@123'; +ALTER TABLE tt_rep FORCE ROW LEVEL SECURITY; +ALTER TABLE par_row_t1 FORCE ROW LEVEL SECURITY; +\d +SELECT * FROM tt_rep ORDER BY id; +SELECT * FROM par_row_t1 ORDER BY id; + +-- check infinite recursion for rls +CREATE TABLE aa(a int); +CREATE TABLE bb(a int); +ALTER TABLE aa ENABLE ROW LEVEL SECURITY; +ALTER TABLE bb ENABLE ROW LEVEL SECURITY; +CREATE ROW LEVEL SECURITY POLICY aa_rls ON aa USING(EXISTS (SELECT a FROM bb)); +-- create failed because of infinite recursion in rls policy +CREATE ROW LEVEL SECURITY POLICY bb_rls ON bb USING(EXISTS (SELECT a FROM aa)); +ALTER TABLE aa DISABLE ROW LEVEL SECURITY; +-- create succeed because of aa disable row level security +CREATE ROW LEVEL SECURITY POLICY bb_rls ON bb USING(EXISTS (SELECT a FROM aa)); +ALTER TABLE aa ENABLE ROW LEVEL SECURITY; +ALTER TABLE aa FORCE ROW LEVEL SECURITY; +ALTER TABLE bb FORCE ROW LEVEL SECURITY; +-- select failed because of infinite recursion in rls policy +SELECT * FROM aa; +ALTER ROW LEVEL SECURITY POLICY aa_rls ON aa USING(a > 10); +ALTER ROW LEVEL SECURITY POLICY aa_rls ON aa USING(EXISTS (SELECT a FROM bb LIMIT 1)); +DROP ROW LEVEL SECURITY POLICY aa_rls ON aa; +CREATE ROW LEVEL SECURITY POLICY aa_rls ON aa AS RESTRICTIVE FOR SELECT TO PUBLIC USING(EXISTS(SELECT a FROM (SELECT a + 100 FROM aa WHERE a > 10 and a < 100 GROUP BY a HAVING count(*) >1))); +DROP TABLE aa CASCADE; +DROP TABLE bb CASCADE; + +-- check any sublink +create table aa(aa_1 int, aa_2 int, rls int); +create policy aa_rls on aa using (rls = 1); +alter table aa enable row level security; +alter table aa force row level security; +create table bb(bb_1 int, bb_2 int, rls int); +create policy bb_rls on bb using (rls = 1); +alter table bb enable row level security; +alter table bb force row level security; +explain(costs off) select aa_1 from aa, bb where bb_1 = 1 and aa_1 > (select min(aa_1) from aa where aa_2 = bb_2 and aa_2 = 1); + +-- clean environment +RESET ROLE; +DROP ROW LEVEL SECURITY POLICY t12 ON inlist_t1; +DROP ROW LEVEL SECURITY POLICY IF EXISTS t12 ON inlist_t1; +DROP SCHEMA regress_rls_schema CASCADE; +DROP USER IF EXISTS regress_rls_alice; +DROP USER IF EXISTS regress_rls_bob; +DROP USER IF EXISTS regress_rls_david; +DROP USER IF EXISTS regress_rls_peter; +DROP USER IF EXISTS regress_rls_admin; +DROP USER IF EXISTS regress_rls_single_user; +DROP ROLE IF EXISTS regress_rls_group1; +DROP ROLE IF EXISTS regress_rls_group2; + +-- check again +SELECT COUNT(*) FROM pg_rlspolicies; +SELECT COUNT(*) FROM pg_depend WHERE classid = 3254 OR refclassid = 3254; +SELECT COUNT(*) FROM pg_shdepend WHERE classid = 3254 OR refclassid = 3254; diff --git a/contrib/dolphin/sql/case_sensitive_test/single_node_foreign_key.sql b/contrib/dolphin/sql/case_sensitive_test/single_node_foreign_key.sql new file mode 100644 index 0000000000000000000000000000000000000000..fa648aa53f63bbec20f7d1837cf31be2708ba25b --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/single_node_foreign_key.sql @@ -0,0 +1,983 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- FOREIGN KEY +-- + +-- MATCH FULL +-- +-- First test, check and cascade +-- +CREATE TABLE PKTABLE ( ptest1 int PRIMARY KEY, ptest2 text ); +CREATE TABLE FKTABLE ( ftest1 int REFERENCES PKTABLE MATCH FULL ON DELETE CASCADE ON UPDATE CASCADE, ftest2 int ); + +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 'Test1'); +INSERT INTO PKTABLE VALUES (2, 'Test2'); +INSERT INTO PKTABLE VALUES (3, 'Test3'); +INSERT INTO PKTABLE VALUES (4, 'Test4'); +INSERT INTO PKTABLE VALUES (5, 'Test5'); + +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2); +INSERT INTO FKTABLE VALUES (2, 3); +INSERT INTO FKTABLE VALUES (3, 4); +INSERT INTO FKTABLE VALUES (NULL, 1); + +-- Insert a failed row into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2); + +-- Check FKTABLE +SELECT * FROM FKTABLE; + +-- Delete a row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=1; + +-- Check FKTABLE for removal of matched row +SELECT * FROM FKTABLE; + +-- Update a row from PK TABLE +UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; + +-- Check FKTABLE for update of matched row +SELECT * FROM FKTABLE; + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + +-- +-- check set NULL and table constraint on multiple columns +-- +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 text, PRIMARY KEY(ptest1, ptest2) ); +CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, CONSTRAINT constrname FOREIGN KEY(ftest1, ftest2) + REFERENCES PKTABLE MATCH FULL ON DELETE SET NULL ON UPDATE SET NULL); + +-- Test comments +COMMENT ON CONSTRAINT constrname_wrong ON FKTABLE IS 'fk constraint comment'; +COMMENT ON CONSTRAINT constrname ON FKTABLE IS 'fk constraint comment'; +COMMENT ON CONSTRAINT constrname ON FKTABLE IS NULL; + +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 2, 'Test1'); +INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2'); +INSERT INTO PKTABLE VALUES (2, 4, 'Test2'); +INSERT INTO PKTABLE VALUES (3, 6, 'Test3'); +INSERT INTO PKTABLE VALUES (4, 8, 'Test4'); +INSERT INTO PKTABLE VALUES (5, 10, 'Test5'); + +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2, 4); +INSERT INTO FKTABLE VALUES (1, 3, 5); +INSERT INTO FKTABLE VALUES (2, 4, 8); +INSERT INTO FKTABLE VALUES (3, 6, 12); +INSERT INTO FKTABLE VALUES (NULL, NULL, 0); + +-- Insert failed rows into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2, 4); +INSERT INTO FKTABLE VALUES (2, 2, 4); +INSERT INTO FKTABLE VALUES (NULL, 2, 4); +INSERT INTO FKTABLE VALUES (1, NULL, 4); + +-- Check FKTABLE +SELECT * FROM FKTABLE; + +-- Delete a row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=1 and ptest2=2; + +-- Check FKTABLE for removal of matched row +SELECT * FROM FKTABLE; + +-- Delete another row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=5 and ptest2=10; + +-- Check FKTABLE (should be no change) +SELECT * FROM FKTABLE; + +-- Update a row from PK TABLE +UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; + +-- Check FKTABLE for update of matched row +SELECT * FROM FKTABLE; + +-- Try altering the column type where foreign keys are involved +ALTER TABLE PKTABLE ALTER COLUMN ptest1 TYPE bigint; +ALTER TABLE FKTABLE ALTER COLUMN ftest1 TYPE bigint; +SELECT * FROM PKTABLE; +SELECT * FROM FKTABLE; + +DROP TABLE PKTABLE CASCADE; +DROP TABLE FKTABLE; + +-- +-- check set default and table constraint on multiple columns +-- +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 text, PRIMARY KEY(ptest1, ptest2) ); +CREATE TABLE FKTABLE ( ftest1 int DEFAULT -1, ftest2 int DEFAULT -2, ftest3 int, CONSTRAINT constrname2 FOREIGN KEY(ftest1, ftest2) + REFERENCES PKTABLE MATCH FULL ON DELETE SET DEFAULT ON UPDATE SET DEFAULT); + +-- Insert a value in PKTABLE for default +INSERT INTO PKTABLE VALUES (-1, -2, 'The Default!'); + +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 2, 'Test1'); +INSERT INTO PKTABLE VALUES (1, 3, 'Test1-2'); +INSERT INTO PKTABLE VALUES (2, 4, 'Test2'); +INSERT INTO PKTABLE VALUES (3, 6, 'Test3'); +INSERT INTO PKTABLE VALUES (4, 8, 'Test4'); +INSERT INTO PKTABLE VALUES (5, 10, 'Test5'); + +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2, 4); +INSERT INTO FKTABLE VALUES (1, 3, 5); +INSERT INTO FKTABLE VALUES (2, 4, 8); +INSERT INTO FKTABLE VALUES (3, 6, 12); +INSERT INTO FKTABLE VALUES (NULL, NULL, 0); + +-- Insert failed rows into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2, 4); +INSERT INTO FKTABLE VALUES (2, 2, 4); +INSERT INTO FKTABLE VALUES (NULL, 2, 4); +INSERT INTO FKTABLE VALUES (1, NULL, 4); + +-- Check FKTABLE +SELECT * FROM FKTABLE; + +-- Delete a row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=1 and ptest2=2; + +-- Check FKTABLE to check for removal +SELECT * FROM FKTABLE; + +-- Delete another row from PK TABLE +DELETE FROM PKTABLE WHERE ptest1=5 and ptest2=10; + +-- Check FKTABLE (should be no change) +SELECT * FROM FKTABLE; + +-- Update a row from PK TABLE +UPDATE PKTABLE SET ptest1=1 WHERE ptest1=2; + +-- Check FKTABLE for update of matched row +SELECT * FROM FKTABLE; + +-- this should fail for lack of CASCADE +DROP TABLE PKTABLE; +DROP TABLE PKTABLE CASCADE; +DROP TABLE FKTABLE; + + +-- +-- First test, check with no on delete or on update +-- +CREATE TABLE PKTABLE ( ptest1 int PRIMARY KEY, ptest2 text ); +CREATE TABLE FKTABLE ( ftest1 int REFERENCES PKTABLE MATCH FULL, ftest2 int ); + +-- Insert test data into PKTABLE +INSERT INTO PKTABLE VALUES (1, 'Test1'); +INSERT INTO PKTABLE VALUES (2, 'Test2'); +INSERT INTO PKTABLE VALUES (3, 'Test3'); +INSERT INTO PKTABLE VALUES (4, 'Test4'); +INSERT INTO PKTABLE VALUES (5, 'Test5'); + +-- Insert successful rows into FK TABLE +INSERT INTO FKTABLE VALUES (1, 2); +INSERT INTO FKTABLE VALUES (2, 3); +INSERT INTO FKTABLE VALUES (3, 4); +INSERT INTO FKTABLE VALUES (NULL, 1); + +-- Insert a failed row into FK TABLE +INSERT INTO FKTABLE VALUES (100, 2); + +-- Check FKTABLE +SELECT * FROM FKTABLE; + +-- Check PKTABLE +SELECT * FROM PKTABLE; + +-- Delete a row from PK TABLE (should fail) +DELETE FROM PKTABLE WHERE ptest1=1; + +-- Delete a row from PK TABLE (should succeed) +DELETE FROM PKTABLE WHERE ptest1=5; + +-- Check PKTABLE for deletes +SELECT * FROM PKTABLE; + +-- Update a row from PK TABLE (should fail) +UPDATE PKTABLE SET ptest1=0 WHERE ptest1=2; + +-- Update a row from PK TABLE (should succeed) +UPDATE PKTABLE SET ptest1=0 WHERE ptest1=4; + +-- Check PKTABLE for updates +SELECT * FROM PKTABLE; + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + + +-- MATCH unspecified + +-- Base test restricting update/delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); +CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE); + +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); + +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); + +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); + +-- Show FKTABLE +SELECT * from FKTABLE; + +-- Try to update something that should fail +UPDATE PKTABLE set ptest2=5 where ptest2=2; + +-- Try to update something that should succeed +UPDATE PKTABLE set ptest1=1 WHERE ptest2=3; + +-- Try to delete something that should fail +DELETE FROM PKTABLE where ptest1=1 and ptest2=2 and ptest3=3; + +-- Try to delete something that should work +DELETE FROM PKTABLE where ptest1=2; + +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; + +SELECT * from FKTABLE; + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + +-- cascade update/delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); +CREATE TABLE FKTABLE ( ftest1 int, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE + ON DELETE CASCADE ON UPDATE CASCADE); + +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); + +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); + +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); + +-- Show FKTABLE +SELECT * from FKTABLE; + +-- Try to update something that will cascade +UPDATE PKTABLE set ptest2=5 where ptest2=2; + +-- Try to update something that should not cascade +UPDATE PKTABLE set ptest1=1 WHERE ptest2=3; + +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; +SELECT * from FKTABLE; + +-- Try to delete something that should cascade +DELETE FROM PKTABLE where ptest1=1 and ptest2=5 and ptest3=3; + +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; +SELECT * from FKTABLE; + +-- Try to delete something that should not have a cascade +DELETE FROM PKTABLE where ptest1=2; + +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; +SELECT * from FKTABLE; + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + +-- set null update / set default delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); +CREATE TABLE FKTABLE ( ftest1 int DEFAULT 0, ftest2 int, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE + ON DELETE SET DEFAULT ON UPDATE SET NULL); + +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); + +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +INSERT INTO FKTABLE VALUES (2, 3, 4, 1); +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); + +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); + +-- Show FKTABLE +SELECT * from FKTABLE; + +-- Try to update something that will set null +UPDATE PKTABLE set ptest2=5 where ptest2=2; + +-- Try to update something that should not set null +UPDATE PKTABLE set ptest2=2 WHERE ptest2=3 and ptest1=1; + +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; +SELECT * from FKTABLE; + +-- Try to delete something that should set default +DELETE FROM PKTABLE where ptest1=2 and ptest2=3 and ptest3=4; + +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; +SELECT * from FKTABLE; + +-- Try to delete something that should not set default +DELETE FROM PKTABLE where ptest2=5; + +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; +SELECT * from FKTABLE; + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + +-- set default update / set null delete +CREATE TABLE PKTABLE ( ptest1 int, ptest2 int, ptest3 int, ptest4 text, PRIMARY KEY(ptest1, ptest2, ptest3) ); +CREATE TABLE FKTABLE ( ftest1 int DEFAULT 0, ftest2 int DEFAULT -1, ftest3 int, ftest4 int, CONSTRAINT constrname3 + FOREIGN KEY(ftest1, ftest2, ftest3) REFERENCES PKTABLE + ON DELETE SET NULL ON UPDATE SET DEFAULT); + +-- Insert Primary Key values +INSERT INTO PKTABLE VALUES (1, 2, 3, 'test1'); +INSERT INTO PKTABLE VALUES (1, 3, 3, 'test2'); +INSERT INTO PKTABLE VALUES (2, 3, 4, 'test3'); +INSERT INTO PKTABLE VALUES (2, 4, 5, 'test4'); +INSERT INTO PKTABLE VALUES (2, -1, 5, 'test5'); + +-- Insert Foreign Key values +INSERT INTO FKTABLE VALUES (1, 2, 3, 1); +INSERT INTO FKTABLE VALUES (2, 3, 4, 1); +INSERT INTO FKTABLE VALUES (2, 4, 5, 1); +INSERT INTO FKTABLE VALUES (NULL, 2, 3, 2); +INSERT INTO FKTABLE VALUES (2, NULL, 3, 3); +INSERT INTO FKTABLE VALUES (NULL, 2, 7, 4); +INSERT INTO FKTABLE VALUES (NULL, 3, 4, 5); + +-- Insert a failed values +INSERT INTO FKTABLE VALUES (1, 2, 7, 6); + +-- Show FKTABLE +SELECT * from FKTABLE; + +-- Try to update something that will fail +UPDATE PKTABLE set ptest2=5 where ptest2=2; + +-- Try to update something that will set default +UPDATE PKTABLE set ptest1=0, ptest2=5, ptest3=10 where ptest2=2; +UPDATE PKTABLE set ptest2=10 where ptest2=4; + +-- Try to update something that should not set default +UPDATE PKTABLE set ptest2=2 WHERE ptest2=3 and ptest1=1; + +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; +SELECT * from FKTABLE; + +-- Try to delete something that should set null +DELETE FROM PKTABLE where ptest1=2 and ptest2=3 and ptest3=4; + +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; +SELECT * from FKTABLE; + +-- Try to delete something that should not set null +DELETE FROM PKTABLE where ptest2=5; + +-- Show PKTABLE and FKTABLE +SELECT * from PKTABLE; +SELECT * from FKTABLE; + +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +CREATE TABLE FKTABLE_FAIL1 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest2) REFERENCES PKTABLE); +CREATE TABLE FKTABLE_FAIL2 ( ftest1 int, CONSTRAINT fkfail1 FOREIGN KEY (ftest1) REFERENCES PKTABLE(ptest2)); + +DROP TABLE FKTABLE_FAIL1; +DROP TABLE FKTABLE_FAIL2; +DROP TABLE PKTABLE; + +-- Test for referencing column number smaller than referenced constraint +CREATE TABLE PKTABLE (ptest1 int, ptest2 int, UNIQUE(ptest1, ptest2)); +CREATE TABLE FKTABLE_FAIL1 (ftest1 int REFERENCES PKTABLE(ptest1)); + +DROP TABLE FKTABLE_FAIL1; +DROP TABLE PKTABLE; + +-- +-- Tests for mismatched types +-- +-- Basic one column, two table setup +CREATE TABLE PKTABLE (ptest1 int PRIMARY KEY); +INSERT INTO PKTABLE VALUES(42); +-- This next should fail, because int=inet does not exist +CREATE TABLE FKTABLE (ftest1 inet REFERENCES PKTABLE); +-- This should also fail for the same reason, but here we +-- give the column name +CREATE TABLE FKTABLE (ftest1 inet REFERENCES PKTABLE(ptest1)); +-- This should succeed, even though they are different types, +-- because int=int8 exists and is a member of the integer opfamily +CREATE TABLE FKTABLE (ftest1 int8 REFERENCES PKTABLE); +-- Check it actually works +INSERT INTO FKTABLE VALUES(42); -- should succeed +INSERT INTO FKTABLE VALUES(43); -- should fail +UPDATE FKTABLE SET ftest1 = ftest1; -- should succeed +UPDATE FKTABLE SET ftest1 = ftest1 + 1; -- should fail +DROP TABLE FKTABLE; +-- This should fail, because we'd have to cast numeric to int which is +-- not an implicit coercion (or use numeric=numeric, but that's not part +-- of the integer opfamily) +CREATE TABLE FKTABLE (ftest1 numeric REFERENCES PKTABLE); +DROP TABLE PKTABLE; +-- On the other hand, this should work because int implicitly promotes to +-- numeric, and we allow promotion on the FK side +CREATE TABLE PKTABLE (ptest1 numeric PRIMARY KEY); +INSERT INTO PKTABLE VALUES(42); +CREATE TABLE FKTABLE (ftest1 int REFERENCES PKTABLE); +-- Check it actually works +INSERT INTO FKTABLE VALUES(42); -- should succeed +INSERT INTO FKTABLE VALUES(43); -- should fail +UPDATE FKTABLE SET ftest1 = ftest1; -- should succeed +UPDATE FKTABLE SET ftest1 = ftest1 + 1; -- should fail +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + +-- Two columns, two tables +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, PRIMARY KEY(ptest1, ptest2)); +-- This should fail, because we just chose really odd types +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE); +-- Again, so should this... +CREATE TABLE FKTABLE (ftest1 cidr, ftest2 timestamp, FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE(ptest1, ptest2)); +-- This fails because we mixed up the column ordering +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES PKTABLE); +-- As does this... +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES PKTABLE(ptest1, ptest2)); +-- And again.. +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE(ptest2, ptest1)); +-- This works... +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest2, ftest1) REFERENCES PKTABLE(ptest2, ptest1)); +DROP TABLE FKTABLE; +-- As does this +CREATE TABLE FKTABLE (ftest1 int, ftest2 inet, FOREIGN KEY(ftest1, ftest2) REFERENCES PKTABLE(ptest1, ptest2)); +DROP TABLE FKTABLE; +DROP TABLE PKTABLE; + +-- Two columns, same table +-- Make sure this still works... +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES PKTABLE(ptest1, ptest2)); +DROP TABLE PKTABLE; +-- And this, +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES PKTABLE); +DROP TABLE PKTABLE; +-- This shouldn't (mixed up columns) +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest3, +ptest4) REFERENCES PKTABLE(ptest2, ptest1)); +-- Nor should this... (same reason, we have 4,3 referencing 1,2 which mismatches types +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, +ptest3) REFERENCES PKTABLE(ptest1, ptest2)); +-- Not this one either... Same as the last one except we didn't defined the columns being referenced. +CREATE TABLE PKTABLE (ptest1 int, ptest2 inet, ptest3 int, ptest4 inet, PRIMARY KEY(ptest1, ptest2), FOREIGN KEY(ptest4, +ptest3) REFERENCES PKTABLE); + +-- +-- Now some cases with Inheritance +-- Basic 2 table case: 1 column of matching types. +create table pktable_base (base1 int not null); +create table PKTABLE (ptest1 int, primary key(base1), unique(base1, ptest1)) Inherits (pktable_base); +create table FKTABLE (ftest1 int references PKTABLE(base1)); +-- now some ins, upd, del +insert into PKTABLE(base1) values (1); +insert into PKTABLE(base1) values (2); +-- let's insert a non-existent FKTABLE value +insert into FKTABLE(ftest1) values (3); +-- let's make a valid row for that +insert into PKTABLE(base1) values (3); +insert into FKTABLE(ftest1) values (3); +-- let's try removing a row that should fail from PKTABLE +delete from PKTABLE where base1>2; +-- okay, let's try updating all of the base1 values to *4 +-- which should fail. +update PKTABLE set base1=base1*4; +-- okay, let's try an update that should work. +update PKTABLE set base1=base1*4 where base1<3; +-- and a delete that should work +delete from PKTABLE where base1>3; +-- cleanup +drop table FKTABLE; +delete from PKTABLE; + +-- Now 2 columns 2 tables, matching types +create table FKTABLE (ftest1 int, ftest2 int, foreign key(ftest1, ftest2) references PKTABLE(base1, ptest1)); +-- now some ins, upd, del +insert into PKTABLE(base1, ptest1) values (1, 1); +insert into PKTABLE(base1, ptest1) values (2, 2); +-- let's insert a non-existent FKTABLE value +insert into FKTABLE(ftest1, ftest2) values (3, 1); +-- let's make a valid row for that +insert into PKTABLE(base1,ptest1) values (3, 1); +insert into FKTABLE(ftest1, ftest2) values (3, 1); +-- let's try removing a row that should fail from PKTABLE +delete from PKTABLE where base1>2; +-- okay, let's try updating all of the base1 values to *4 +-- which should fail. +update PKTABLE set base1=base1*4; +-- okay, let's try an update that should work. +update PKTABLE set base1=base1*4 where base1<3; +-- and a delete that should work +delete from PKTABLE where base1>3; +-- cleanup +drop table FKTABLE; +drop table PKTABLE; +drop table pktable_base; + +-- Now we'll do one all in 1 table with 2 columns of matching types +create table pktable_base(base1 int not null, base2 int); +create table PKTABLE(ptest1 int, ptest2 int, primary key(base1, ptest1), foreign key(base2, ptest2) references + PKTABLE(base1, ptest1)) Inherits (pktable_base); +insert into PKTABLE (base1, ptest1, base2, ptest2) values (1, 1, 1, 1); +insert into PKTABLE (base1, ptest1, base2, ptest2) values (2, 1, 1, 1); +insert into PKTABLE (base1, ptest1, base2, ptest2) values (2, 2, 2, 1); +insert into PKTABLE (base1, ptest1, base2, ptest2) values (1, 3, 2, 2); +-- fails (3,2) isn't in base1, ptest1 +insert into PKTABLE (base1, ptest1, base2, ptest2) values (2, 3, 3, 2); +-- fails (2,2) is being referenced +delete from PKTABLE where base1=2; +-- fails (1,1) is being referenced (twice) +update PKTABLE set base1=3 where base1=1; +-- this sequence of two deletes will work, since after the first there will be no (2,*) references +delete from PKTABLE where base2=2; +delete from PKTABLE where base1=2; +drop table PKTABLE; +drop table pktable_base; + +-- 2 columns (2 tables), mismatched types +create table pktable_base(base1 int not null); +create table PKTABLE(ptest1 inet, primary key(base1, ptest1)) Inherits (pktable_base); +-- just generally bad types (with and without column references on the referenced table) +create table FKTABLE(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references PKTABLE); +create table FKTABLE(ftest1 cidr, ftest2 int[], foreign key (ftest1, ftest2) references PKTABLE(base1, ptest1)); +-- let's mix up which columns reference which +create table FKTABLE(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references PKTABLE); +create table FKTABLE(ftest1 int, ftest2 inet, foreign key(ftest2, ftest1) references PKTABLE(base1, ptest1)); +create table FKTABLE(ftest1 int, ftest2 inet, foreign key(ftest1, ftest2) references PKTABLE(ptest1, base1)); +drop table PKTABLE; +drop table pktable_base; + +-- 2 columns (1 table), mismatched types +create table pktable_base(base1 int not null, base2 int); +create table PKTABLE(ptest1 inet, ptest2 inet[], primary key(base1, ptest1), foreign key(base2, ptest2) references + PKTABLE(base1, ptest1)) Inherits (pktable_base); +create table PKTABLE(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(base2, ptest2) references + PKTABLE(ptest1, base1)) Inherits (pktable_base); +create table PKTABLE(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references + PKTABLE(base1, ptest1)) Inherits (pktable_base); +create table PKTABLE(ptest1 inet, ptest2 inet, primary key(base1, ptest1), foreign key(ptest2, base2) references + PKTABLE(base1, ptest1)) Inherits (pktable_base); +drop table PKTABLE; +drop table pktable_base; + +-- +-- Deferrable constraints +-- (right now, only FOREIGN KEY constraints can be deferred) +-- + +-- deferrable, explicitly deferred +CREATE TABLE PKTABLE ( + id INT4 PRIMARY KEY, + other INT4 +); + +CREATE TABLE FKTABLE ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES PKTABLE DEFERRABLE +); + +-- default to immediate: should fail +INSERT INTO FKTABLE VALUES (5, 10); + +-- explicitly defer the constraint +BEGIN; + +SET CONSTRAINTS ALL DEFERRED; + +INSERT INTO FKTABLE VALUES (10, 15); +INSERT INTO PKTABLE VALUES (15, 0); -- make the FK insert valid + +COMMIT; + +DROP TABLE FKTABLE, PKTABLE; + +-- deferrable, initially deferred +CREATE TABLE PKTABLE ( + id INT4 PRIMARY KEY, + other INT4 +); + +CREATE TABLE FKTABLE ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES PKTABLE DEFERRABLE INITIALLY DEFERRED +); + +-- default to deferred, should succeed +BEGIN; + +INSERT INTO FKTABLE VALUES (100, 200); +INSERT INTO PKTABLE VALUES (200, 500); -- make the FK insert valid + +COMMIT; + +-- default to deferred, explicitly make immediate +BEGIN; + +SET CONSTRAINTS ALL IMMEDIATE; + +-- should fail +INSERT INTO FKTABLE VALUES (500, 1000); + +COMMIT; + +DROP TABLE FKTABLE, PKTABLE; + +-- tricky behavior: according to SQL99, if a deferred constraint is set +-- to 'immediate' mode, it should be checked for validity *immediately*, +-- not when the current transaction commits (i.e. the mode change applies +-- retroactively) +CREATE TABLE PKTABLE ( + id INT4 PRIMARY KEY, + other INT4 +); + +CREATE TABLE FKTABLE ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES PKTABLE DEFERRABLE +); + +BEGIN; + +SET CONSTRAINTS ALL DEFERRED; + +-- should succeed, for now +INSERT INTO FKTABLE VALUES (1000, 2000); + +-- should cause transaction abort, due to preceding error +SET CONSTRAINTS ALL IMMEDIATE; + +INSERT INTO PKTABLE VALUES (2000, 3); -- too late + +COMMIT; + +DROP TABLE FKTABLE, PKTABLE; + +-- deferrable, initially deferred +CREATE TABLE PKTABLE ( + id INT4 PRIMARY KEY, + other INT4 +); + +CREATE TABLE FKTABLE ( + id INT4 PRIMARY KEY, + fk INT4 REFERENCES PKTABLE DEFERRABLE INITIALLY DEFERRED +); + +BEGIN; + +-- no error here +INSERT INTO FKTABLE VALUES (100, 200); + +-- error here on commit +COMMIT; + +DROP TABLE PKTABLE, FKTABLE; + +-- test notice about expensive referential integrity checks, +-- where the index cannot be used because of type incompatibilities. + +CREATE TEMP TABLE PKTABLE ( + id1 INT4 PRIMARY KEY, + id2 VARCHAR(4) UNIQUE, + id3 REAL UNIQUE, + UNIQUE(id1, id2, id3) +); + +CREATE TEMP TABLE FKTABLE ( + x1 INT4 REFERENCES PKTABLE(id1), + x2 VARCHAR(4) REFERENCES PKTABLE(id2), + x3 REAL REFERENCES PKTABLE(id3), + x4 TEXT, + x5 INT2 +); + +-- check individual constraints with alter table. + +-- should fail + +-- varchar does not promote to real +ALTER TABLE FKTABLE ADD CONSTRAINT fk_2_3 +FOREIGN KEY (x2) REFERENCES PKTABLE(id3); + +-- nor to int4 +ALTER TABLE FKTABLE ADD CONSTRAINT fk_2_1 +FOREIGN KEY (x2) REFERENCES PKTABLE(id1); + +-- real does not promote to int4 +ALTER TABLE FKTABLE ADD CONSTRAINT fk_3_1 +FOREIGN KEY (x3) REFERENCES PKTABLE(id1); + +-- int4 does not promote to text +ALTER TABLE FKTABLE ADD CONSTRAINT fk_1_2 +FOREIGN KEY (x1) REFERENCES PKTABLE(id2); + +-- should succeed + +-- int4 promotes to real +ALTER TABLE FKTABLE ADD CONSTRAINT fk_1_3 +FOREIGN KEY (x1) REFERENCES PKTABLE(id3); + +-- text is compatible with varchar +ALTER TABLE FKTABLE ADD CONSTRAINT fk_4_2 +FOREIGN KEY (x4) REFERENCES PKTABLE(id2); + +-- int2 is part of integer opfamily as of 8.0 +ALTER TABLE FKTABLE ADD CONSTRAINT fk_5_1 +FOREIGN KEY (x5) REFERENCES PKTABLE(id1); + +-- check multikey cases, especially out-of-order column lists + +-- these should work + +ALTER TABLE FKTABLE ADD CONSTRAINT fk_123_123 +FOREIGN KEY (x1,x2,x3) REFERENCES PKTABLE(id1,id2,id3); + +ALTER TABLE FKTABLE ADD CONSTRAINT fk_213_213 +FOREIGN KEY (x2,x1,x3) REFERENCES PKTABLE(id2,id1,id3); + +ALTER TABLE FKTABLE ADD CONSTRAINT fk_253_213 +FOREIGN KEY (x2,x5,x3) REFERENCES PKTABLE(id2,id1,id3); + +-- these should fail + +ALTER TABLE FKTABLE ADD CONSTRAINT fk_123_231 +FOREIGN KEY (x1,x2,x3) REFERENCES PKTABLE(id2,id3,id1); + +ALTER TABLE FKTABLE ADD CONSTRAINT fk_241_132 +FOREIGN KEY (x2,x4,x1) REFERENCES PKTABLE(id1,id3,id2); + +DROP TABLE PKTABLE, FKTABLE; + +-- test a tricky case: we can elide firing the FK check trigger during +-- an UPDATE if the UPDATE did not change the foreign key +-- field. However, we can't do this if our transaction was the one that +-- created the updated row and the trigger is deferred, since our UPDATE +-- will have invalidated the original newly-inserted tuple, and therefore +-- cause the on-INSERT RI trigger not to be fired. + +CREATE TEMP TABLE PKTABLE ( + id int primary key, + other int +); + +CREATE TEMP TABLE FKTABLE ( + id int primary key, + fk int references PKTABLE deferrable initially deferred +); + +INSERT INTO PKTABLE VALUES (5, 10); + +BEGIN; + +-- doesn't match PK, but no error yet +INSERT INTO FKTABLE VALUES (0, 20); + +-- don't change FK +UPDATE FKTABLE SET id = id + 1; + +-- should catch error from initial INSERT +COMMIT; + +-- check same case when insert is in a different subtransaction than update + +BEGIN; + +-- doesn't match PK, but no error yet +INSERT INTO FKTABLE VALUES (0, 20); + +-- UPDATE will be in a subxact +SAVEPOINT savept1; + +-- don't change FK +UPDATE FKTABLE SET id = id + 1; + +-- should catch error from initial INSERT +COMMIT; + +BEGIN; + +-- INSERT will be in a subxact +SAVEPOINT savept1; + +-- doesn't match PK, but no error yet +INSERT INTO FKTABLE VALUES (0, 20); + +RELEASE SAVEPOINT savept1; + +-- don't change FK +UPDATE FKTABLE SET id = id + 1; + +-- should catch error from initial INSERT +COMMIT; + +BEGIN; + +-- doesn't match PK, but no error yet +INSERT INTO FKTABLE VALUES (0, 20); + +-- UPDATE will be in a subxact +SAVEPOINT savept1; + +-- don't change FK +UPDATE FKTABLE SET id = id + 1; + +-- Roll back the UPDATE +ROLLBACK TO savept1; + +-- should catch error from initial INSERT +COMMIT; + +-- test order of firing of FK triggers when several RI-induced changes need to +-- be made to the same row. This was broken by subtransaction-related +-- changes in 8.0. + +CREATE TEMP TABLE users ( + id INT PRIMARY KEY, + name VARCHAR NOT NULL +); + +INSERT INTO users VALUES (1, 'Jozko'); +INSERT INTO users VALUES (2, 'Ferko'); +INSERT INTO users VALUES (3, 'Samko'); + +CREATE TEMP TABLE tasks ( + id INT PRIMARY KEY, + owner INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL, + worker INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL, + checked_by INT REFERENCES users ON UPDATE CASCADE ON DELETE SET NULL +); + +INSERT INTO tasks VALUES (1,1,NULL,NULL); +INSERT INTO tasks VALUES (2,2,2,NULL); +INSERT INTO tasks VALUES (3,3,3,3); + +SELECT * FROM tasks; + +UPDATE users SET id = 4 WHERE id = 3; + +SELECT * FROM tasks; + +DELETE FROM users WHERE id = 4; + +SELECT * FROM tasks; + +-- could fail with only 2 changes to make, if row was already updated +BEGIN; +UPDATE tasks set id=id WHERE id=2; +SELECT * FROM tasks; +DELETE FROM users WHERE id = 2; +SELECT * FROM tasks; +COMMIT; + +-- +-- Test self-referential FK with CASCADE (bug #6268) +-- +create temp table selfref ( + a int primary key, + b int, + foreign key (b) references selfref (a) + on update cascade on delete cascade +); + +insert into selfref (a, b) +values + (0, 0), + (1, 1); + +begin; + update selfref set a = 123 where a = 0; + select a, b from selfref; + update selfref set a = 456 where a = 123; + select a, b from selfref; +commit; + +-- +-- Test deferred FK check on a tuple deleted by a rolled-back subtransaction +-- +create table pktable2(f1 int primary key); +create table fktable2(f1 int references pktable2 deferrable initially deferred); +insert into pktable2 values(1); + +begin; +insert into fktable2 values(1); +savepoint x; +delete from fktable2; +rollback to x; +commit; + +begin; +insert into fktable2 values(2); +savepoint x; +delete from fktable2; +rollback to x; +commit; -- fail + +-- +-- Test that we prevent dropping FK constraint with pending trigger events +-- +begin; +insert into fktable2 values(2); +alter table fktable2 drop constraint fktable2_f1_fkey; +commit; + +begin; +delete from pktable2 where f1 = 1; +alter table fktable2 drop constraint fktable2_f1_fkey; +commit; + +drop table pktable2, fktable2; diff --git a/contrib/dolphin/sql/case_sensitive_test/single_node_triggers.sql b/contrib/dolphin/sql/case_sensitive_test/single_node_triggers.sql new file mode 100644 index 0000000000000000000000000000000000000000..4d708ec343fe04461c76c04cb51e9d97945e6fbe --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/single_node_triggers.sql @@ -0,0 +1,1048 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- TRIGGERS +-- +create table Pkeys (pkey1 int4 not null, pkey2 text not null); +alter table Pkeys add unique(pkey1, pkey2); +create table Fkeys (fkey1 int4, fkey2 text, fkey3 int); +create table Fkeys2 (fkey21 int4, fkey22 text, pkey23 int not null); + +create index fkeys_i on Fkeys (fkey1, fkey2); +create index fkeys2_i on Fkeys2 (fkey21, fkey22); +create index fkeys2p_i on Fkeys2 (pkey23); + +insert into Pkeys values (10, '1'); +insert into Pkeys values (20, '2'); +insert into Pkeys values (30, '3'); +insert into Pkeys values (40, '4'); +insert into Pkeys values (50, '5'); +insert into Pkeys values (60, '6'); +create unique index pkeys_i on Pkeys (pkey1, pkey2); + +-- +-- For Fkeys: +-- (fkey1, fkey2) --> Pkeys (pkey1, pkey2) +-- (fkey3) --> Fkeys2 (pkey23) +-- +create trigger check_fkeys_pkey_exist + before insert or update on Fkeys + for each row + execute procedure + check_primary_key ('fkey1', 'fkey2', 'Pkeys', 'pkey1', 'pkey2'); + +create trigger check_fkeys_pkey2_exist + before insert or update on Fkeys + for each row + execute procedure check_primary_key ('fkey3', 'Fkeys2', 'pkey23'); + +-- +-- For Fkeys2: +-- (fkey21, fkey22) --> Pkeys (pkey1, pkey2) +-- +create trigger check_fkeys2_pkey_exist + before insert or update on Fkeys2 + for each row + execute procedure + check_primary_key ('fkey21', 'fkey22', 'Pkeys', 'pkey1', 'pkey2'); + +-- Test comments +COMMENT ON TRIGGER check_fkeys2_pkey_bad ON Fkeys2 IS 'wrong'; +COMMENT ON TRIGGER check_fkeys2_pkey_exist ON Fkeys2 IS 'right'; +COMMENT ON TRIGGER check_fkeys2_pkey_exist ON Fkeys2 IS NULL; + +-- +-- For Pkeys: +-- ON DELETE/UPDATE (pkey1, pkey2) CASCADE: +-- Fkeys (fkey1, fkey2) and Fkeys2 (fkey21, fkey22) +-- +create trigger check_pkeys_fkey_cascade + before delete or update on Pkeys + for each row + execute procedure + check_foreign_key (2, 'cascade', 'pkey1', 'pkey2', + 'Fkeys', 'fkey1', 'fkey2', 'Fkeys2', 'fkey21', 'fkey22'); + +-- +-- For Fkeys2: +-- ON DELETE/UPDATE (pkey23) RESTRICT: +-- Fkeys (fkey3) +-- +create trigger check_fkeys2_fkey_restrict + before delete or update on Fkeys2 + for each row + execute procedure check_foreign_key (1, 'restrict', 'pkey23', 'Fkeys', 'fkey3'); + +insert into Fkeys2 values (10, '1', 1); +insert into Fkeys2 values (30, '3', 2); +insert into Fkeys2 values (40, '4', 5); +insert into Fkeys2 values (50, '5', 3); +-- no key in Pkeys +insert into Fkeys2 values (70, '5', 3); + +insert into Fkeys values (10, '1', 2); +insert into Fkeys values (30, '3', 3); +insert into Fkeys values (40, '4', 2); +insert into Fkeys values (50, '5', 2); +-- no key in Pkeys +insert into Fkeys values (70, '5', 1); +-- no key in Fkeys2 +insert into Fkeys values (60, '6', 4); + +delete from Pkeys where pkey1 = 30 and pkey2 = '3'; +delete from Pkeys where pkey1 = 40 and pkey2 = '4'; +update Pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 50 and pkey2 = '5'; +update Pkeys set pkey1 = 7, pkey2 = '70' where pkey1 = 10 and pkey2 = '1'; + +DROP TABLE Pkeys; +DROP TABLE Fkeys; +DROP TABLE Fkeys2; + +-- -- I've disabled the funny_dup17 test because the new semantics +-- -- of AFTER ROW triggers, which get now fired at the end of a +-- -- query always, cause funny_dup17 to enter an endless loop. +-- -- +-- -- Jan +-- +-- create table dup17 (x int4); +-- +-- create trigger dup17_before +-- before insert on dup17 +-- for each row +-- execute procedure +-- funny_dup17 () +-- ; +-- +-- insert into dup17 values (17); +-- select count(*) from dup17; +-- insert into dup17 values (17); +-- select count(*) from dup17; +-- +-- drop trigger dup17_before on dup17; +-- +-- create trigger dup17_after +-- after insert on dup17 +-- for each row +-- execute procedure +-- funny_dup17 () +-- ; +-- insert into dup17 values (13); +-- select count(*) from dup17 where x = 13; +-- insert into dup17 values (13); +-- select count(*) from dup17 where x = 13; +-- +-- DROP TABLE dup17; + +create sequence ttdummy_seq increment 10 start 0 minvalue 0; + +create table TTtest ( + price_id int4, + price_val int4, + price_on int4, + price_off int4 default 999999 +); +ALTER TABLE TTtest ADD PRIMARY KEY(price_id, price_val, price_on, price_off); + +create trigger ttdummy + before delete or update on TTtest + for each row + execute procedure + ttdummy (price_on, price_off); + +create trigger ttserial + before insert or update on TTtest + for each row + execute procedure + autoinc (price_on, ttdummy_seq); + +insert into TTtest values (1, 1, null); +insert into TTtest values (2, 2, null); +insert into TTtest values (3, 3, 0); + +select * from TTtest order by 1,2,3,4; +delete from TTtest where price_id = 2; +select * from TTtest order by 1,2,3,4; +-- what do we see ? + +-- get current prices +select * from TTtest where price_off = 999999 order by 1,2,3,4; + +-- change price for price_id == 3 +update TTtest set price_val = 30 where price_id = 3; +select * from TTtest order by 1,2,3,4; + +-- now we want to change pric_id in ALL tuples +-- this gets us not what we need +update TTtest set price_id = 5 where price_id = 3; +select * from TTtest order by 1,2,3,4; + +-- restore data as before last update: +select set_ttdummy(0); +delete from TTtest where price_id = 5; +update TTtest set price_off = 999999 where price_val = 30; +select * from TTtest order by 1,2,3,4; + +-- and try change price_id now! +update TTtest set price_id = 5 where price_id = 3; +select * from TTtest order by 1,2,3,4; +-- isn't it what we need ? + +select set_ttdummy(1); + +-- we want to correct some "date" +update TTtest set price_on = -1 where price_id = 1; +-- but this doesn't work + +-- try in this way +select set_ttdummy(0); +update TTtest set price_on = -1 where price_id = 1; +select * from TTtest order by 1,2,3,4; +-- isn't it what we need ? + +-- get price for price_id == 5 as it was @ "date" 35 +select * from TTtest where price_on <= 35 and price_off > 35 and price_id = 5 order by 1,2,3,4; + +drop table TTtest; +drop sequence ttdummy_seq; + +-- +-- tests for per-statement triggers +-- + +CREATE TABLE Log_table (tstamp timestamp default timeofday()::timestamp); + +CREATE TABLE Main_table (a int, b int); +ALTER TABLE Main_table ADD PRIMARY KEY(A, B); + +COPY Main_table (a,b) FROM stdin; +5 10 +20 20 +30 10 +50 35 +80 15 +\. + +CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS ' +BEGIN + RAISE NOTICE ''trigger_func(%) called: action = %, when = %, level = %'', TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL; + RETURN NULL; +END;'; + +CREATE TRIGGER before_ins_stmt_trig BEFORE INSERT ON Main_table +FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('before_ins_stmt'); + +CREATE TRIGGER after_ins_stmt_trig AFTER INSERT ON Main_table +FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('after_ins_stmt'); + +-- +-- if neither 'FOR EACH ROW' nor 'FOR EACH STATEMENT' was specified, +-- CREATE TRIGGER should default to 'FOR EACH STATEMENT' +-- +CREATE TRIGGER after_upd_stmt_trig AFTER UPDATE ON Main_table +EXECUTE PROCEDURE trigger_func('after_upd_stmt'); + +CREATE TRIGGER after_upd_row_trig AFTER UPDATE ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_row'); + +INSERT INTO Main_table DEFAULT VALUES; + +UPDATE Main_table SET a = a + 1 WHERE b < 30; +-- UPDATE that effects zero rows should still call per-statement trigger +UPDATE Main_table SET a = a + 2 WHERE b > 100; + +-- COPY should fire per-row and per-statement INSERT triggers +COPY Main_table (a, b) FROM stdin; +30 40 +50 60 +\. + +SELECT * FROM Main_table ORDER BY a, b; + +-- +-- test triggers with WHEN clause +-- + +CREATE TRIGGER modified_a BEFORE UPDATE OF a ON Main_table +FOR EACH ROW WHEN (OLD.a <> NEW.a) EXECUTE PROCEDURE trigger_func('modified_a'); +CREATE TRIGGER modified_any BEFORE UPDATE OF a ON Main_table +FOR EACH ROW WHEN (OLD.* IS DISTINCT FROM NEW.*) EXECUTE PROCEDURE trigger_func('modified_any'); +CREATE TRIGGER insert_a AFTER INSERT ON Main_table +FOR EACH ROW WHEN (NEW.a = 123) EXECUTE PROCEDURE trigger_func('insert_a'); +CREATE TRIGGER delete_a AFTER DELETE ON Main_table +FOR EACH ROW WHEN (OLD.a = 123) EXECUTE PROCEDURE trigger_func('delete_a'); +CREATE TRIGGER insert_when BEFORE INSERT ON Main_table +FOR EACH STATEMENT WHEN (true) EXECUTE PROCEDURE trigger_func('insert_when'); +CREATE TRIGGER delete_when AFTER DELETE ON Main_table +FOR EACH STATEMENT WHEN (true) EXECUTE PROCEDURE trigger_func('delete_when'); +INSERT INTO Main_table (a) VALUES (123), (456); +COPY Main_table FROM stdin; +123 999 +456 999 +\. +; + +DELETE FROM Main_table WHERE a IN (123, 456); +UPDATE Main_table SET a = 50, b = 60; +SELECT * FROM Main_table ORDER BY a, b; +SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'Main_table'::regclass AND tgname = 'modified_a'; +SELECT pg_get_triggerdef(oid, false) FROM pg_trigger WHERE tgrelid = 'Main_table'::regclass AND tgname = 'modified_a'; +SELECT pg_get_triggerdef(oid, true) FROM pg_trigger WHERE tgrelid = 'Main_table'::regclass AND tgname = 'modified_any'; +DROP TRIGGER modified_a ON Main_table; +DROP TRIGGER modified_any ON Main_table; +DROP TRIGGER insert_a ON Main_table; +DROP TRIGGER delete_a ON Main_table; +DROP TRIGGER insert_when ON Main_table; +DROP TRIGGER delete_when ON Main_table; + +-- Test column-level triggers +DROP TRIGGER after_upd_row_trig ON Main_table; + +CREATE TRIGGER before_upd_a_row_trig BEFORE UPDATE OF a ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_upd_a_row'); +CREATE TRIGGER after_upd_b_row_trig AFTER UPDATE OF b ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_b_row'); +CREATE TRIGGER after_upd_a_b_row_trig AFTER UPDATE OF a, b ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('after_upd_a_b_row'); + +CREATE TRIGGER before_upd_a_stmt_trig BEFORE UPDATE OF a ON Main_table +FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('before_upd_a_stmt'); +CREATE TRIGGER after_upd_b_stmt_trig AFTER UPDATE OF b ON Main_table +FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func('after_upd_b_stmt'); + +SELECT pg_get_triggerdef(oid) FROM pg_trigger WHERE tgrelid = 'Main_table'::regclass AND tgname = 'after_upd_a_b_row_trig'; + +UPDATE Main_table SET a = 50; +UPDATE Main_table SET b = 10; + +-- +-- Test case for bug with BEFORE trigger followed by AFTER trigger with WHEN +-- + +CREATE TABLE some_t (some_col boolean NOT NULL); +ALTER TABLE some_t ADD PRIMARY KEY(some_col); +CREATE FUNCTION dummy_update_func() RETURNS trigger AS $$ +BEGIN + RAISE NOTICE 'dummy_update_func(%) called: action = %, old = %, new = %', + TG_ARGV[0], TG_OP, OLD, NEW; + RETURN NEW; +END; +$$ LANGUAGE plpgsql; +CREATE TRIGGER some_trig_before BEFORE UPDATE ON some_t FOR EACH ROW + EXECUTE PROCEDURE dummy_update_func('before'); +CREATE TRIGGER some_trig_aftera AFTER UPDATE ON some_t FOR EACH ROW + WHEN (NOT OLD.some_col AND NEW.some_col) + EXECUTE PROCEDURE dummy_update_func('aftera'); +CREATE TRIGGER some_trig_afterb AFTER UPDATE ON some_t FOR EACH ROW + WHEN (NOT NEW.some_col) + EXECUTE PROCEDURE dummy_update_func('afterb'); +INSERT INTO some_t VALUES (TRUE); +UPDATE some_t SET some_col = TRUE; +UPDATE some_t SET some_col = FALSE; +UPDATE some_t SET some_col = TRUE; +DROP TABLE some_t; + +-- bogus cases +CREATE TRIGGER error_upd_and_col BEFORE UPDATE OR UPDATE OF a ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('error_upd_and_col'); +CREATE TRIGGER error_upd_a_a BEFORE UPDATE OF a, a ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('error_upd_a_a'); +CREATE TRIGGER error_ins_a BEFORE INSERT OF a ON Main_table +FOR EACH ROW EXECUTE PROCEDURE trigger_func('error_ins_a'); +CREATE TRIGGER error_ins_when BEFORE INSERT OR UPDATE ON Main_table +FOR EACH ROW WHEN (OLD.a <> NEW.a) +EXECUTE PROCEDURE trigger_func('error_ins_old'); +CREATE TRIGGER error_del_when BEFORE DELETE OR UPDATE ON Main_table +FOR EACH ROW WHEN (OLD.a <> NEW.a) +EXECUTE PROCEDURE trigger_func('error_del_new'); +CREATE TRIGGER error_del_when BEFORE INSERT OR UPDATE ON Main_table +FOR EACH ROW WHEN (NEW.tableoid <> 0) +EXECUTE PROCEDURE trigger_func('error_when_sys_column'); +CREATE TRIGGER error_stmt_when BEFORE UPDATE OF a ON Main_table +FOR EACH STATEMENT WHEN (OLD.* IS DISTINCT FROM NEW.*) +EXECUTE PROCEDURE trigger_func('error_stmt_when'); + +-- check dependency restrictions +ALTER TABLE Main_table DROP COLUMN b; +-- this should succeed, but we'll roll it back to keep the triggers around +start transaction; +DROP TRIGGER after_upd_a_b_row_trig ON Main_table; +DROP TRIGGER after_upd_b_row_trig ON Main_table; +DROP TRIGGER after_upd_b_stmt_trig ON Main_table; +ALTER TABLE Main_table DROP COLUMN b; +rollback; + +-- Test enable/disable triggers + +create table Trigtest (i serial primary key); +-- test that disabling RI triggers works +create table Trigtest2 (i int references Trigtest(i) on delete cascade); + +create function Trigtest() returns trigger as $$ +begin + raise notice '% % % %', TG_RELNAME, TG_OP, TG_WHEN, TG_LEVEL; + return new; +end;$$ language plpgsql; + +create trigger trigtest_b_row_tg before insert or update or delete on Trigtest +for each row execute procedure Trigtest(); +create trigger trigtest_a_row_tg after insert or update or delete on Trigtest +for each row execute procedure Trigtest(); +create trigger trigtest_b_stmt_tg before insert or update or delete on Trigtest +for each statement execute procedure Trigtest(); +create trigger trigtest_a_stmt_tg after insert or update or delete on Trigtest +for each statement execute procedure Trigtest(); + +insert into Trigtest default values; +alter table Trigtest disable trigger trigtest_b_row_tg; +insert into Trigtest default values; +alter table Trigtest disable trigger user; +insert into Trigtest default values; +alter table Trigtest enable trigger trigtest_a_stmt_tg; +insert into Trigtest default values; +insert into Trigtest2 values(1); +insert into Trigtest2 values(2); +delete from Trigtest where i=2; +select * from Trigtest2 order by 1; +alter table Trigtest disable trigger all; +delete from Trigtest where i=1; +select * from Trigtest2 order by 1; +-- ensure we still insert, even when all triggers are disabled +insert into Trigtest default values; +select * from Trigtest order by 1; +drop table Trigtest2; +drop table Trigtest; + + +-- dump trigger data +CREATE TABLE Trigger_test ( + i int, + v varchar +); + +CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger +LANGUAGE plpgsql AS $$ + +declare + + argstr text; + relid text; + +begin + + relid := TG_relid::regclass; + + -- plpgsql can't discover its trigger data in a hash like perl and python + -- can, or by a sort of reflection like tcl can, + -- so we have to hard code the names. + raise NOTICE 'TG_NAME: %', TG_name; + raise NOTICE 'TG_WHEN: %', TG_when; + raise NOTICE 'TG_LEVEL: %', TG_level; + raise NOTICE 'TG_OP: %', TG_op; + raise NOTICE 'TG_RELID::regclass: %', relid; + raise NOTICE 'TG_RELNAME: %', TG_relname; + raise NOTICE 'TG_TABLE_NAME: %', TG_table_name; + raise NOTICE 'TG_TABLE_SCHEMA: %', TG_table_schema; + raise NOTICE 'TG_NARGS: %', TG_nargs; + + argstr := '['; + for i in 0 .. TG_nargs - 1 loop + if i > 0 then + argstr := argstr || ', '; + end if; + argstr := argstr || TG_argv[i]; + end loop; + argstr := argstr || ']'; + raise NOTICE 'TG_ARGV: %', argstr; + + if TG_OP != 'INSERT' then + raise NOTICE 'OLD: %', OLD; + end if; + + if TG_OP != 'DELETE' then + raise NOTICE 'NEW: %', NEW; + end if; + + if TG_OP = 'DELETE' then + return OLD; + else + return NEW; + end if; + +end; +$$; + +CREATE TRIGGER show_trigger_data_trig +BEFORE INSERT OR UPDATE OR DELETE ON Trigger_test +FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); + +insert into Trigger_test values(1,'insert'); +update Trigger_test set v = 'update' where i = 1; +delete from Trigger_test; + +DROP TRIGGER show_trigger_data_trig on Trigger_test; + +DROP FUNCTION trigger_data(); + +DROP TABLE Trigger_test; + +-- +-- Test use of row comparisons on OLD/NEW +-- + +CREATE TABLE Trigger_test1 (f1 int, f2 text, f3 text); +CREATE TABLE Trigger_test2 (f1 int, f2 text, f3 text); +-- this is the obvious (and wrong...) way to compare rows +CREATE FUNCTION mytrigger() RETURNS trigger LANGUAGE plpgsql as $$ +begin + if row(old.*) = row(new.*) then + raise notice 'row % not changed', new.f1; + else + raise notice 'row % changed', new.f1; + end if; + return new; +end$$; + +CREATE TRIGGER t_trigger_test1 +BEFORE UPDATE ON Trigger_test1 +FOR EACH ROW EXECUTE PROCEDURE mytrigger(); +CREATE TRIGGER t_trigger_test2 +BEFORE UPDATE ON Trigger_test2 +FOR EACH ROW EXECUTE PROCEDURE mytrigger(); + +INSERT INTO Trigger_test1 VALUES(1, 'foo', 'bar'); +INSERT INTO Trigger_test2 VALUES(2, 'baz', 'quux'); + +UPDATE Trigger_test1 SET f3 = 'bar'; +UPDATE Trigger_test2 SET f3 = 'bar'; +UPDATE Trigger_test1 SET f3 = NULL; +UPDATE Trigger_test2 SET f3 = NULL; +-- this demonstrates that the above isn't really working as desired: +UPDATE Trigger_test1 SET f3 = NULL; +UPDATE Trigger_test2 SET f3 = NULL; + + +-- the right way when considering nulls is +CREATE OR REPLACE FUNCTION mytrigger() RETURNS trigger LANGUAGE plpgsql as $$ +begin + if row(old.*) is distinct from row(new.*) then + raise notice 'row % changed', new.f1; + else + raise notice 'row % not changed', new.f1; + end if; + return new; +end$$; + +UPDATE Trigger_test1 SET f3 = 'bar'; +UPDATE Trigger_test2 SET f3 = 'bar'; +UPDATE Trigger_test1 SET f3 = NULL; +UPDATE Trigger_test2 SET f3 = NULL; +UPDATE Trigger_test1 SET f3 = NULL; +UPDATE Trigger_test2 SET f3 = NULL; + +DROP TABLE Trigger_test1; +DROP TABLE Trigger_test2; + +DROP FUNCTION mytrigger(); + +-- Test snapshot management in serializable transactions involving triggers +-- per bug report in 6bc73d4c0910042358k3d1adff3qa36f8df75198ecea@mail.gmail.com +CREATE FUNCTION serializable_update_trig() RETURNS trigger LANGUAGE plpgsql AS +$$ +declare + rec record; +begin + new.description = 'updated in trigger'; + return new; +end; +$$; + +CREATE TABLE serializable_update_tab ( + id int, + filler text, + description text +); +ALTER TABLE serializable_update_tab ADD PRIMARY KEY(id); + +CREATE TRIGGER serializable_update_trig BEFORE UPDATE ON serializable_update_tab + FOR EACH ROW EXECUTE PROCEDURE serializable_update_trig(); + +INSERT INTO serializable_update_tab SELECT a, repeat('xyzxz', 100), 'new' + FROM generate_series(1, 50) a; + +START TRANSACTION; +SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; +UPDATE serializable_update_tab SET description = 'no no', id = 1 WHERE id = 1; +COMMIT; +SELECT description FROM serializable_update_tab WHERE id = 1; +DROP TABLE serializable_update_tab; + +-- minimal update trigger + +CREATE TABLE Min_updates_test ( + f1 text, + f2 int, + f3 int); +ALTER TABLE Min_updates_test ADD PRIMARY KEY(F1, F2); + +CREATE TABLE Min_updates_test_oids ( + f1 text, + f2 int, + f3 int) WITH OIDS; +ALTER TABLE Min_updates_test_oids ADD PRIMARY KEY(F1, F2); + +INSERT INTO Min_updates_test VALUES ('a',1,2),('b','2',null); + +INSERT INTO Min_updates_test_oids VALUES ('a',1,2),('b','2',null); + +CREATE TRIGGER z_min_update +BEFORE UPDATE ON Min_updates_test +FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); + +CREATE TRIGGER z_min_update +BEFORE UPDATE ON Min_updates_test_oids +FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger(); + +\set QUIET false + +UPDATE Min_updates_test SET f1 = f1; + +UPDATE Min_updates_test SET f2 = f2 + 1; + +UPDATE Min_updates_test SET f3 = 2 WHERE f3 is null; + +UPDATE Min_updates_test_oids SET f1 = f1; + +UPDATE Min_updates_test_oids SET f2 = f2 + 1; + +UPDATE Min_updates_test_oids SET f3 = 2 WHERE f3 is null; + +\set QUIET true + +SELECT * FROM Min_updates_test ORDER BY 1,2,3; + +SELECT * FROM Min_updates_test_oids ORDER BY 1,2,3; + +DROP TABLE Min_updates_test; + +DROP TABLE Min_updates_test_oids; + +-- +-- Test triggers on views +-- + +CREATE VIEW main_view AS SELECT a, b FROM Main_table; + +-- Updates should fail without rules or triggers +INSERT INTO main_view VALUES (1,2); +UPDATE main_view SET b = 20 WHERE a = 50; +DELETE FROM main_view WHERE a = 50; +-- Should fail even when there are no matching rows +DELETE FROM main_view WHERE a = 51; + +-- VIEW trigger function +CREATE OR REPLACE FUNCTION view_trigger() RETURNS trigger +LANGUAGE plpgsql AS $$ +declare + argstr text := ''; +begin + for i in 0 .. TG_nargs - 1 loop + if i > 0 then + argstr := argstr || ', '; + end if; + argstr := argstr || TG_argv[i]; + end loop; + + raise notice '% % % % (%)', TG_RELNAME, TG_WHEN, TG_OP, TG_LEVEL, argstr; + + if TG_LEVEL = 'ROW' then + if TG_OP = 'INSERT' then + raise NOTICE 'NEW: %', NEW; + INSERT INTO Main_table VALUES (NEW.a, NEW.b); + RETURN NEW; + end if; + + if TG_OP = 'UPDATE' then + raise NOTICE 'OLD: %, NEW: %', OLD, NEW; + UPDATE Main_table SET a = NEW.a, b = NEW.b WHERE a = OLD.a AND b = OLD.b; + if NOT FOUND then RETURN NULL; end if; + RETURN NEW; + end if; + + if TG_OP = 'DELETE' then + raise NOTICE 'OLD: %', OLD; + DELETE FROM Main_table WHERE a = OLD.a AND b = OLD.b; + if NOT FOUND then RETURN NULL; end if; + RETURN OLD; + end if; + end if; + + RETURN NULL; +end; +$$; + +-- Before row triggers aren't allowed on views +CREATE TRIGGER invalid_trig BEFORE INSERT ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_ins_row'); + +CREATE TRIGGER invalid_trig BEFORE UPDATE ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_upd_row'); + +CREATE TRIGGER invalid_trig BEFORE DELETE ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_del_row'); + +-- After row triggers aren't allowed on views +CREATE TRIGGER invalid_trig AFTER INSERT ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_ins_row'); + +CREATE TRIGGER invalid_trig AFTER UPDATE ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_upd_row'); + +CREATE TRIGGER invalid_trig AFTER DELETE ON main_view +FOR EACH ROW EXECUTE PROCEDURE trigger_func('before_del_row'); + +-- Truncate triggers aren't allowed on views +CREATE TRIGGER invalid_trig BEFORE TRUNCATE ON main_view +EXECUTE PROCEDURE trigger_func('before_tru_row'); + +CREATE TRIGGER invalid_trig AFTER TRUNCATE ON main_view +EXECUTE PROCEDURE trigger_func('before_tru_row'); + +-- INSTEAD OF triggers aren't allowed on tables +CREATE TRIGGER invalid_trig INSTEAD OF INSERT ON Main_table +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_ins'); + +CREATE TRIGGER invalid_trig INSTEAD OF UPDATE ON Main_table +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_upd'); + +CREATE TRIGGER invalid_trig INSTEAD OF DELETE ON Main_table +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_del'); + +-- Don't support WHEN clauses with INSTEAD OF triggers +CREATE TRIGGER invalid_trig INSTEAD OF UPDATE ON main_view +FOR EACH ROW WHEN (OLD.a <> NEW.a) EXECUTE PROCEDURE view_trigger('instead_of_upd'); + +-- Don't support column-level INSTEAD OF triggers +CREATE TRIGGER invalid_trig INSTEAD OF UPDATE OF a ON main_view +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_upd'); + +-- Don't support statement-level INSTEAD OF triggers +CREATE TRIGGER invalid_trig INSTEAD OF UPDATE ON main_view +EXECUTE PROCEDURE view_trigger('instead_of_upd'); + +-- Valid INSTEAD OF triggers +CREATE TRIGGER instead_of_insert_trig INSTEAD OF INSERT ON main_view +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_ins'); + +CREATE TRIGGER instead_of_update_trig INSTEAD OF UPDATE ON main_view +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_upd'); + +CREATE TRIGGER instead_of_delete_trig INSTEAD OF DELETE ON main_view +FOR EACH ROW EXECUTE PROCEDURE view_trigger('instead_of_del'); + +-- Valid BEFORE statement VIEW triggers +CREATE TRIGGER before_ins_stmt_trig BEFORE INSERT ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_ins_stmt'); + +CREATE TRIGGER before_upd_stmt_trig BEFORE UPDATE ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_upd_stmt'); + +CREATE TRIGGER before_del_stmt_trig BEFORE DELETE ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('before_view_del_stmt'); + +-- Valid AFTER statement VIEW triggers +CREATE TRIGGER after_ins_stmt_trig AFTER INSERT ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_ins_stmt'); + +CREATE TRIGGER after_upd_stmt_trig AFTER UPDATE ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_upd_stmt'); + +CREATE TRIGGER after_del_stmt_trig AFTER DELETE ON main_view +FOR EACH STATEMENT EXECUTE PROCEDURE view_trigger('after_view_del_stmt'); + +\set QUIET false + +-- Insert into view using trigger +INSERT INTO main_view VALUES (20, 30); +INSERT INTO main_view VALUES (21, 31) RETURNING a, b; + +-- Table trigger will prevent updates +UPDATE main_view SET b = 31 WHERE a = 20; +UPDATE main_view SET b = 32 WHERE a = 21 AND b = 31 RETURNING a, b; + +-- Remove table trigger to allow updates +DROP TRIGGER before_upd_a_row_trig ON Main_table; +UPDATE main_view SET b = 31 WHERE a = 20; +UPDATE main_view SET b = 32 WHERE a = 21 AND b = 31 RETURNING a, b; + +-- Before and after stmt triggers should fire even when no rows are affected +UPDATE main_view SET b = 0 WHERE false; + +-- Delete from view using trigger +DELETE FROM main_view WHERE a IN (20,21); +DELETE FROM main_view WHERE a = 31 RETURNING a, b; + +\set QUIET true + +-- Describe view should list triggers +\d "main_view" + +-- Test dropping view triggers +DROP TRIGGER instead_of_insert_trig ON main_view; +DROP TRIGGER instead_of_delete_trig ON main_view; +\d+ "main_view" +DROP VIEW main_view; + +-- +-- Test triggers on a join view +-- +CREATE TABLE country_table ( + country_id serial primary key, + country_name text unique not null, + continent text not null +); + +INSERT INTO country_table (country_name, continent) + VALUES ('Japan', 'Asia'), + ('UK', 'Europe'), + ('USA', 'North America') + RETURNING *; + +CREATE TABLE city_table ( + city_id serial primary key, + city_name text not null, + population bigint, + country_id int references country_table +); + +CREATE VIEW city_view AS + SELECT city_id, city_name, population, country_name, continent + FROM city_table ci + LEFT JOIN country_table co ON co.country_id = ci.country_id; + +CREATE FUNCTION city_insert() RETURNS trigger LANGUAGE plpgsql AS $$ +declare + ctry_id int; +begin + if NEW.country_name IS NOT NULL then + SELECT country_id, continent INTO ctry_id, NEW.continent + FROM country_table WHERE country_name = NEW.country_name; + if NOT FOUND then + raise exception 'No such country: "%"', NEW.country_name; + end if; + else + NEW.continent := NULL; + end if; + + if NEW.city_id IS NOT NULL then + INSERT INTO city_table + VALUES(NEW.city_id, NEW.city_name, NEW.population, ctry_id); + else + INSERT INTO city_table(city_name, population, country_id) + VALUES(NEW.city_name, NEW.population, ctry_id) + RETURNING city_id INTO NEW.city_id; + end if; + + RETURN NEW; +end; +$$; + +CREATE TRIGGER city_insert_trig INSTEAD OF INSERT ON city_view +FOR EACH ROW EXECUTE PROCEDURE city_insert(); + +CREATE FUNCTION city_delete() RETURNS trigger LANGUAGE plpgsql AS $$ +begin + DELETE FROM city_table WHERE city_id = OLD.city_id; + if NOT FOUND then RETURN NULL; end if; + RETURN OLD; +end; +$$; + +CREATE TRIGGER city_delete_trig INSTEAD OF DELETE ON city_view +FOR EACH ROW EXECUTE PROCEDURE city_delete(); + +CREATE FUNCTION city_update() RETURNS trigger LANGUAGE plpgsql AS $$ +declare + ctry_id int; +begin + if NEW.country_name IS DISTINCT FROM OLD.country_name then + SELECT country_id, continent INTO ctry_id, NEW.continent + FROM country_table WHERE country_name = NEW.country_name; + if NOT FOUND then + raise exception 'No such country: "%"', NEW.country_name; + end if; + + UPDATE city_table SET city_name = NEW.city_name, + population = NEW.population, + country_id = ctry_id + WHERE city_id = OLD.city_id; + else + UPDATE city_table SET city_name = NEW.city_name, + population = NEW.population + WHERE city_id = OLD.city_id; + NEW.continent := OLD.continent; + end if; + + if NOT FOUND then RETURN NULL; end if; + RETURN NEW; +end; +$$; + +CREATE TRIGGER city_update_trig INSTEAD OF UPDATE ON city_view +FOR EACH ROW EXECUTE PROCEDURE city_update(); + +\set QUIET false + +-- INSERT .. RETURNING +INSERT INTO city_view(city_name) VALUES('Tokyo') RETURNING *; +INSERT INTO city_view(city_name, population) VALUES('London', 7556900) RETURNING *; +INSERT INTO city_view(city_name, country_name) VALUES('Washington DC', 'USA') RETURNING *; +INSERT INTO city_view(city_id, city_name) VALUES(123456, 'New York') RETURNING *; +INSERT INTO city_view VALUES(234567, 'Birmingham', 1016800, 'UK', 'EU') RETURNING *; + +-- UPDATE .. RETURNING +UPDATE city_view SET country_name = 'Japon' WHERE city_name = 'Tokyo'; -- error +UPDATE city_view SET country_name = 'Japan' WHERE city_name = 'Takyo'; -- no match +UPDATE city_view SET country_name = 'Japan' WHERE city_name = 'Tokyo' RETURNING *; -- OK + +UPDATE city_view SET population = 13010279 WHERE city_name = 'Tokyo' RETURNING *; +UPDATE city_view SET country_name = 'UK' WHERE city_name = 'New York' RETURNING *; +UPDATE city_view SET country_name = 'USA', population = 8391881 WHERE city_name = 'New York' RETURNING *; +UPDATE city_view SET continent = 'EU' WHERE continent = 'Europe' RETURNING *; +UPDATE city_view v1 SET country_name = v2.country_name FROM city_view v2 + WHERE v2.city_name = 'Birmingham' AND v1.city_name = 'London' RETURNING *; + +-- DELETE .. RETURNING +DELETE FROM city_view WHERE city_name = 'Birmingham' RETURNING *; + +\set QUIET true + +-- read-only view with WHERE clause +CREATE VIEW european_city_view AS + SELECT * FROM city_view WHERE continent = 'Europe'; +SELECT count(*) FROM european_city_view; + +CREATE FUNCTION no_op_trig_fn() RETURNS trigger LANGUAGE plpgsql +AS 'begin RETURN NULL; end'; + +CREATE TRIGGER no_op_trig INSTEAD OF INSERT OR UPDATE OR DELETE +ON european_city_view FOR EACH ROW EXECUTE PROCEDURE no_op_trig_fn(); + +\set QUIET false + +INSERT INTO european_city_view VALUES (0, 'x', 10000, 'y', 'z'); +UPDATE european_city_view SET population = 10000; +DELETE FROM european_city_view; + +\set QUIET true + +-- rules bypassing no-op triggers +CREATE RULE european_city_insert_rule AS ON INSERT TO european_city_view +DO INSTEAD INSERT INTO city_view +VALUES (NEW.city_id, NEW.city_name, NEW.population, NEW.country_name, NEW.continent) +RETURNING *; + +CREATE RULE european_city_update_rule AS ON UPDATE TO european_city_view +DO INSTEAD UPDATE city_view SET + city_name = NEW.city_name, + population = NEW.population, + country_name = NEW.country_name +WHERE city_id = OLD.city_id +RETURNING NEW.*; + +CREATE RULE european_city_delete_rule AS ON DELETE TO european_city_view +DO INSTEAD DELETE FROM city_view WHERE city_id = OLD.city_id RETURNING *; + +\set QUIET false + +-- INSERT not limited by view's WHERE clause, but UPDATE AND DELETE are +INSERT INTO european_city_view(city_name, country_name) + VALUES ('Cambridge', 'USA') RETURNING *; +UPDATE european_city_view SET country_name = 'UK' + WHERE city_name = 'Cambridge'; +DELETE FROM european_city_view WHERE city_name = 'Cambridge'; + +-- UPDATE and DELETE via rule and trigger +UPDATE city_view SET country_name = 'UK' + WHERE city_name = 'Cambridge' RETURNING *; +UPDATE european_city_view SET population = 122800 + WHERE city_name = 'Cambridge' RETURNING *; +DELETE FROM european_city_view WHERE city_name = 'Cambridge' RETURNING *; + +-- join UPDATE test +UPDATE city_view v SET population = 599657 + FROM city_table ci, country_table co + WHERE ci.city_name = 'Washington DC' and co.country_name = 'USA' + AND v.city_id = ci.city_id AND v.country_name = co.country_name + RETURNING co.country_id, v.country_name, + v.city_id, v.city_name, v.population; + +\set QUIET true + +SELECT * FROM city_view order by 1; + +DROP TABLE city_table CASCADE; +DROP TABLE country_table; + + +-- Test pg_trigger_depth() + +create table depth_A (id int not null primary key); +create table depth_B (id int not null primary key); +create table depth_C (id int not null primary key); + +create function depth_a_tf() returns trigger + language plpgsql as $$ +begin + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + insert into depth_B values (new.id); + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + return new; +end; +$$; +create trigger depth_a_tr before insert on depth_A + for each row execute procedure depth_a_tf(); + +create function depth_b_tf() returns trigger + language plpgsql as $$ +begin + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + begin + execute 'insert into depth_C values (' || new.id::text || ')'; + -- exception + -- when sqlstate 'U9999' then + -- raise notice 'SQLSTATE = U9999: depth = %', pg_trigger_depth(); + end; + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + if new.id = 1 then + execute 'insert into depth_C values (' || new.id::text || ')'; + end if; + return new; +end; +$$; +create trigger depth_b_tr before insert on depth_B + for each row execute procedure depth_b_tf(); + +create function depth_c_tf() returns trigger + language plpgsql as $$ +begin + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + if new.id = 1 then + raise exception sqlstate 'U9999'; + end if; + raise notice '%: depth = %', tg_name, pg_trigger_depth(); + return new; +end; +$$; +create trigger depth_c_tr before insert on depth_C + for each row execute procedure depth_c_tf(); + +select pg_trigger_depth(); +insert into depth_A values (1); +select pg_trigger_depth(); +insert into depth_A values (2); +select pg_trigger_depth(); + +drop table depth_A, depth_B, depth_C; +drop function depth_a_tf(); +drop function depth_b_tf(); +drop function depth_c_tf(); diff --git a/contrib/dolphin/sql/case_sensitive_test/temp.sql b/contrib/dolphin/sql/case_sensitive_test/temp.sql new file mode 100644 index 0000000000000000000000000000000000000000..a0d58f6e63b5fa30ba7e65df5fea9da6065486bf --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/temp.sql @@ -0,0 +1,324 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- TEMP +-- Test temp relations and indexes +-- + +-- Enforce use of COMMIT instead of 2PC for temporary objects + +-- test temp table/index masking + +CREATE TABLE temptest(col int); + +CREATE INDEX i_temptest ON temptest(col); + +CREATE TEMP TABLE temptest(tcol int); + +CREATE INDEX i_temptest ON temptest(tcol); + +SELECT * FROM temptest; + +DROP INDEX i_temptest; + +DROP TABLE temptest; + +SELECT * FROM temptest; + +DROP INDEX i_temptest; + +DROP TABLE temptest; + +-- test temp table selects + +CREATE TABLE temptest(col int); + +INSERT INTO temptest VALUES (1); + +CREATE TEMP TABLE temptest(tcol float); + +INSERT INTO temptest VALUES (2.1); + +SELECT * FROM temptest; + +DROP TABLE temptest; + +SELECT * FROM temptest; + +DROP TABLE temptest; + +-- test temp table deletion + +CREATE TEMP TABLE temptest(col int); + +\c + +-- Enforce use of COMMIT instead of 2PC for temporary objects + +SELECT * FROM temptest; + +-- Test ON COMMIT DELETE ROWS + +CREATE TEMP TABLE temptest(col int) ON COMMIT DELETE ROWS; +START TRANSACTION; +INSERT INTO temptest VALUES (1); +INSERT INTO temptest VALUES (2); + +SELECT * FROM temptest ORDER BY 1; +COMMIT; + +SELECT * FROM temptest; + +DROP TABLE temptest; + +START TRANSACTION; +CREATE TEMP TABLE temptest(col) ON COMMIT PRESERVE ROWS AS SELECT 1; + +SELECT * FROM temptest; +COMMIT; + +SELECT * FROM temptest; + +DROP TABLE temptest; + +-- Test ON COMMIT DROP + +START TRANSACTION; + +CREATE TEMP TABLE temptest(col int) ON COMMIT DROP; + +INSERT INTO temptest VALUES (1); +INSERT INTO temptest VALUES (2); + +SELECT * FROM temptest ORDER BY 1; +COMMIT; + +SELECT * FROM temptest; + +START TRANSACTION; +CREATE TEMP TABLE temptest(col) ON COMMIT DROP AS SELECT 1; + +SELECT * FROM temptest; +COMMIT; + +SELECT * FROM temptest; + +-- Test foreign keys +START TRANSACTION; +CREATE TEMP TABLE temptest1(col int PRIMARY KEY); +CREATE TEMP TABLE temptest2(col int REFERENCES temptest1) + ON COMMIT DELETE ROWS; +INSERT INTO temptest1 VALUES (1); +INSERT INTO temptest2 VALUES (1); +COMMIT; +SELECT * FROM temptest1; +SELECT * FROM temptest2; + +START TRANSACTION; +CREATE TEMP TABLE temptest3(col int PRIMARY KEY) ON COMMIT DELETE ROWS; +CREATE TEMP TABLE temptest4(col int REFERENCES temptest3); +COMMIT; + +-- Test manipulation of temp schema's placement in search path + +create table public.whereami (f1 text); +insert into public.whereami values ('public'); + +create temp table whereami (f1 text); +insert into whereami values ('temp'); + +create function public.whoami() returns text + as $$select 'public'::text$$ language sql; + +create function pg_temp.whoami() returns text + as $$select 'temp'::text$$ language sql; + +-- default should have pg_temp implicitly first, but only for tables +select * from whereami; +select whoami(); + +-- can list temp first explicitly, but it still doesn't affect functions +set search_path = pg_temp, public; +select * from whereami; +select whoami(); + +-- or put it last for security +set search_path = public, pg_temp; +select * from whereami; +select whoami(); + +-- you can invoke a temp function explicitly, though +select pg_temp.whoami(); + +drop table public.whereami; + + +--TEST CASE FOR TEMP TABLE +--1. temp table's feature: +-- 1). Coordinator isolation +-- 2). Session isolation. +-- 3). Auto drop when session quit. +-- 4). Unlogged +-- 5). Other features are the same as ordinary table. + +--2. temp table's SQL interface: +-- 1) Create +-- 2) Use +-- 3) Analyze +-- 4) Truncate +-- 5) Discard +-- 6) Alter + + +--Prepare +create table test_ordinary(a int, b int); +insert into test_ordinary select generate_series(1, 1000), generate_series(1, 1000); +create index ordinary_idx on test_ordinary(a); + +create table col_ordinary(a int) with (orientation = column); +insert into col_ordinary select a from test_ordinary; + +create sequence test_seq; + +create schema test_temp; + +create temp table test_base(a int); +insert into test_base select generate_series(1, 1000); + +create temp table test_temp1(a int, b varchar2(3000)); +insert into test_temp1 select a, lpad(a, 3000, '-') from test_base; +create index temp1_idx on test_temp1(a, b); + +create temp table test_temp2(a int, b varchar2(3000)); +insert into test_temp2 select a, lpad(a, 3000, '+') from test_base; +create index temp2_idx on test_temp2(a); + +create temp table temp_col1(a int, b varchar2(3000)) with (orientation = column); +insert into temp_col1 select * from test_temp1; +create index col1_idx on temp_col1(a); + +create temp table temp_col2(a int, b varchar2(3000)) with (orientation = column); +insert into temp_col2 select * from temp_col1; + +--Session isolation + +--Auto drop when session quit. + +--Unlogged + +--Other features + +--temp function + +--Create temp table +create local temp table tl(a int, b varchar2(3000)); +create local temporary table lt(a int, b varchar2(3000)); +create temp table pg_temp.temp_t(a int); +create table pg_temp.temp_t1(a int); +create temp table temp_t2 as select * from temp_t1; +create temp table pg_temp.temp_t3 as select * from temp_t1; +create table pg_temp.temp_t4 as select * from temp_t1; +create temp table pg_temp.temp_t5(like temp_t1); +create temp table temp_t6(like temp_t1); +create table pg_temp.temp_t7(like temp_t1); +select * from pg_temp.temp_t1; +--Analyze +Analyze test_base; +Analyze test_temp1; +select relname, relpages, reltuples from pg_class where relname = 'test_temp1'; +Analyze pg_temp.test_temp2; +select relname, relpages, reltuples from pg_class where relname = 'test_temp2'; +Analyze temp_col1; +select relname, relpages, reltuples from pg_class where relname = 'temp_col1'; +select relname, relpages, reltuples from pg_class where relname = 'temp_col2'; +Analyze temp_col2; + +--Use +select a/0 from test_temp1; +select * from test_temp1 order by 1 limit 30; +select t1.a, t2.a from test_temp1 t1, test_temp2 t2 where t1.a = t2.a order by t1.a limit 50; +select t1.a, t2.a from test_temp1 t1, test_ordinary t2 where t1.a = t2.a order by t1.a limit 50; + +select t1.a, t2.b from test_temp1 t1, test_ordinary t2 where t1.a = t2.b order by t1.a limit 50; + +explain select t1.a, t2.a from test_temp1 t1, test_col t2 where t1.a = t2.a order by t1.a limit 50; +select t1.a, t2.a from test_temp1 t1, test_col t2 where t1.a = t2.a order by t1.a limit 50; + +--test Alter +Alter table test_temp1 rename to test_temp3; +Alter table test_temp3 set schema pg_temp; +Alter table test_temp3 set schema public; +Alter table test_temp3 rename to test_temp1; + + +--Col Table +select t1.a from temp_col1 t1, col_ordinary t2 where t1.a = t2.a order by 1 limit 30; +select t1.a from temp_col1 t1, temp_col2 t2 where t1.a = t2.a order by 1 limit 30; +select t1.a from test_temp1 t1, temp_col1 t2 where t1.a = t2.a order by 1 limit 30; + +Alter temp_col1 rename to temp_col2; +Create view col_v1 as select * from temp_col2; +Alter view col_v1 alter a set default 1; +Drop view col_v1; + +--test View +create view v1 as select * from test_temp1; +select a from v1 order by 1 limit 50; +create view v2 as select t1.a from test_temp1 t1, test_ordinary t2 where t1.a = t2.a; +select a from v2 order by a limit 50; + +create view v3 as select t1.a from test_temp1 t1, test_temp2 t2 where t1.a = t2.a; +select a from v3 order by a limit 50; + +alter view v2 rename to v4; +alter view v4 alter a set default 1; + +alter view v4 set schema test_temp; + +create view v5 as select * from test_ordinary; + +drop view v1, v5; +drop view v1; +drop view v3,v4; + + +--test SEQ +create temp sequence temp_seq; +alter sequence temp_seq rename to temp_seq1; +alter sequence temp_seq1 minvalue 10; +drop sequence test_seq; +create temp table test_serial(a serial, b varchar2(100)); +create temp table test_serial2(a int); +alter table test_serial2 add b serial; +drop table test_serial; +drop table test_serial2; + +--test rule + +--test trigger + +--test Reindex +reindex index temp1_idx, ordinary_idx; +reindex index temp1_idx; +reindex index temp2_idx; +reindex table test_temp1; +--test Drop index +drop index temp1_idx, ordinary_idx; +drop index temp1_idx, temp2_idx; + +--Vacuum +vacuum test_temp1; +vacuum test_temp2; +vacuum full test_temp1; +vacuum full test_temp2; +--Truncate +Truncate test_base; +Truncate test_temp1; +Truncate test_temp2; +Truncate test_col; + +--Test Drop +Drop table test_base; +Drop table test_temp1, test_ordinary; +Drop table test_temp1, test_temp2; +Drop table temp_col1, temp_col2; \ No newline at end of file diff --git a/contrib/dolphin/sql/case_sensitive_test/update.sql b/contrib/dolphin/sql/case_sensitive_test/update.sql new file mode 100644 index 0000000000000000000000000000000000000000..c9c4602387de8fb5b17e6f66c85ab136b9ce35d8 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/update.sql @@ -0,0 +1,343 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- UPDATE syntax tests +-- + +CREATE TABLE Update_Test ( + a INT DEFAULT 10, + b INT, + c TEXT +); + +INSERT INTO Update_Test VALUES (5, 10, 'foo'); +INSERT INTO Update_Test(b, a) VALUES (15, 10); + +SELECT * FROM Update_Test ORDER BY a, b, c; + +UPDATE Update_Test SET a = DEFAULT, b = DEFAULT; + +SELECT * FROM Update_Test ORDER BY a, b, c; + +-- aliases for the UPDATE target table +UPDATE Update_Test AS t SET b = 10 WHERE t.a = 10; + +SELECT * FROM Update_Test ORDER BY a, b, c; + +UPDATE Update_Test t SET b = t.b + 10 WHERE t.a = 10; + +SELECT * FROM Update_Test ORDER BY a, b, c; + +-- +-- Test VALUES in FROM +-- + +UPDATE Update_Test SET a=v.i FROM (VALUES(100, 20)) AS v(i, j) + WHERE Update_Test.b = v.j; + +SELECT * FROM Update_Test ORDER BY a, b, c; + +-- +-- Test multiple-set-clause syntax +-- + +UPDATE Update_Test SET (c,b,a) = ('bugle', b+11, DEFAULT) WHERE c = 'foo'; +SELECT * FROM Update_Test ORDER BY a, b, c; +UPDATE Update_Test SET (c,b) = ('car', a+b), a = a + 1 WHERE a = 10; +SELECT * FROM Update_Test ORDER BY a, b, c; +-- fail, multi assignment to same column: +UPDATE Update_Test SET (c,b) = ('car', a+b), b = a + 1 WHERE a = 10; + +-- XXX this should work, but doesn't yet: +UPDATE Update_Test SET (a,b) = (select a,b FROM Update_Test where c = 'foo') + WHERE a = 10; + +-- if an alias for the target table is specified, don't allow references +-- to the original table name +UPDATE Update_Test AS t SET b = Update_Test.b + 10 WHERE t.a = 10; + +-- Make sure that we can update to a TOASTed value. +UPDATE Update_Test SET c = repeat('x', 10000) WHERE c = 'car'; +SELECT a, b, char_length(c) FROM Update_Test ORDER BY a; + +DROP TABLE Update_Test; + +--Test "update tablename AS aliasname SET aliasname.colname = colvalue;" +CREATE TABLE Update_Test_c( + a INT DEFAULT 10 +); +CREATE TABLE Update_Test_d( + a INT DEFAULT 10, + b INT +); + +INSERT INTO Update_Test_c (a) VALUES (1); +SELECT * FROM Update_Test_c; +UPDATE Update_Test_c AS test_c SET test_c.a = 2; +SELECT * FROM Update_Test_c; +UPDATE Update_Test_c AS test_c SET test_c.a = 3 WHERE test_c.a = 2; +SELECT * FROM Update_Test_c; +UPDATE Update_Test_c test_c SET test_c.a = 4; +SELECT * FROM Update_Test_c; +UPDATE Update_Test_c AS test_c SET test_c.a = 5 WHERE test_c.a = 4; +SELECT * FROM Update_Test_c; +UPDATE Update_Test_c AS test_c SET test_a.a = 6; +SELECT * FROM Update_Test_c; +UPDATE Update_Test_c test_c SET test_a.a = 7; +SELECT * FROM Update_Test_c; + +INSERT INTO Update_Test_d (a,b) VALUES (1,2); +SELECT * FROM Update_Test_d; +UPDATE Update_Test_d AS test_D SET test_D.a = 3, test_D.b = 4; +SELECT * FROM Update_Test_d; +UPDATE Update_Test_d AS test_D SET test_D.a = 5, test_D.b = 6 WHERE test_D.a = 3 AND test_D.b = 4; +SELECT * FROM Update_Test_d; +UPDATE Update_Test_d test_D SET test_D.a = 7, test_D.b = 8; +SELECT * FROM Update_Test_d; +UPDATE Update_Test_d test_D SET test_D.a = 9, test_D.b = 10 WHERE test_D.a = 7 AND test_D.b = 8; +SELECT * FROM Update_Test_d; +UPDATE Update_Test_d AS test_D SET test_D.a = 11, test_b.b = 12; +SELECT * FROM Update_Test_d; +UPDATE Update_Test_d test_D SET test_D.a = 11, test_b.b = 12; +SELECT * FROM Update_Test_d; + +DROP TABLE Update_Test_c; +DROP TABLE Update_Test_d; +DROP TABLE Update_Test_d; + +create table tbl_Update(a1 int,a2 varchar2(100)); +ALTER TABLE tbl_Update ADD PRIMARY KEY(a1); +delete from tbl_Update; +insert into tbl_Update values(1,'a'); +insert into tbl_Update values(2,'b'); +insert into tbl_Update values(3,'c'); +insert into tbl_Update values(4,'d'); +insert into tbl_Update values(11,'AA'); +select * from tbl_Update order by a1; +create table sub_tab(T1 int,t2 varchar2(100)); +insert into sub_tab values(11,'AA'); +select * from sub_tab; +update tbl_Update a set (a1,a2)=(100,'hello') from sub_tab t where t.T1=a.a1; +select * from tbl_Update order by a1; +update tbl_Update a1 set (a1,a2)=(101,'hello world') from sub_tab t where t.T1=a1.a1; +select * from tbl_Update order by a1; +drop table tbl_Update; +drop table sub_tab; + +create table test_tbl_A(a int); +insert into test_tbl_A values(1); +select * from test_tbl_A; +update test_tbl_A a set a=2; +select * from test_tbl_A; +update test_tbl_A a set a=3 where a.a=2; +select * from test_tbl_A; +drop table test_tbl_A; + +create table test_tbl_B(a int, b int); +insert into test_tbl_B values(1,2); +select * from test_tbl_B; +update test_tbl_B as a set (a,b)=(3,4); +update test_tbl_B set c = 100; +select * from test_tbl_B; +update test_tbl_B as a set (a,b)=(5,6) where a.a=3 and a.b=4; +select * from test_tbl_B; +update test_tbl_B as a set (a.a, a.b)=(7,8) where a.a=5 and a.b=6; +select * from test_tbl_B; +drop table test_tbl_B; + +CREATE TYPE complex AS (b int,c int); +CREATE TYPE complex AS (b int,c int); +create table test_tbl_C(a complex); +ALTER TABLE test_tbl_C ADD PRIMARY KEY(a); +insert into test_tbl_C values((1,2)); +select * from test_tbl_C; +update test_tbl_C col set col.a.b=(100); +select * from test_tbl_C; +drop table test_tbl_C; +drop type complex; + +-- Test multiple column set with GROUP BY of UPDATE +CREATE TABLE Update_Multiple_Set_01(a INT, b INT, c INT); +CREATE TABLE Update_Multiple_Set_02(a INT, b INT, c INT); +UPDATE Update_Multiple_Set_02 t2 SET (b, c) = (SELECT b, c FROM Update_Multiple_Set_01 T1 WHERE T1.a=t2.a GROUP BY 1, 2); +DROP TABLE Update_Multiple_Set_01; +DROP TABLE Update_Multiple_Set_02; + +-- Test multiple column set with GROUP BY alias of UPDATE +drop table Usview08t; +drop table Offers_20050701; +create table Usview08t(location_id int, on_hand_unit_qty int, on_order_qty int); +create table Offers_20050701(location_id int null, visits int null); +insert into Usview08t values(1,3,5); +insert into Offers_20050701 values(2,4); +UPDATE Usview08t Table_008 SET (on_hand_unit_qty,on_order_qty) = (SELECT AVG(VISITS),154 c2 FROM Offers_20050701 GROUP BY c2); +select * from Usview08t; +UPDATE Usview08t t2 SET (t2.on_hand_unit_qty, t2.on_order_qty) = (SELECT AVG(VISITS),154 FROM Offers_20050701); +UPDATE Usview08t Table_008 SET (on_hand_unit_qty,on_hand_unit_qty) = (SELECT AVG(VISITS),154 c2 FROM Offers_20050701 GROUP BY c2); +drop table Usview08t; +drop table Offers_20050701; + +--Test table name reference or alias reference +create table Test (b int, a int); +insert into Test values(1,2); +update Test set Test.a=10; +update Test t set t.b=20; +select * from Test; +drop table Test; + +create table Test(a int[3],b int); +insert into Test values('{1,2,3}',4); +update Test set Test.a='{10,20,30}'; +select * from Test; +update Test t set t.a='{11,21,31}'; +select * from Test; +update Test set a='{12,22,32}'; +select * from Test; +update Test set a[1,2]='{13,23}'; +select * from Test; +--must compatible with previous features, though not perfect +update Test set Test.a[1,2]='{14,24}'; +select * from Test; +update Test t set t.a[1,2]='{15,25}'; +select * from Test; +drop table Test; + +create type newtype as(a int, b int); +create table Test(a newtype,b int); +insert into Test values(ROW(1,2),3); +update Test set Test.a=ROW(10,20); +select * from Test; +update Test t set t.a=ROW(11,21); +select * from Test; +--Ambiguous scene +--update field a of column a rather than column a of table a +update Test a set a.a=12; +--update field b of column a rather than column b of table a +update Test a set a.b=22; +select * from Test; +--fail +update Test a set a.a=ROW(13,23); +update Test a set a.c=10; +update Test b set b.c=10; +--must compatible with previous features, though not perfect +update Test a set a.a.a=12; +select * from Test; +drop table Test; +drop type newtype; + +--Test update in merge into +create table test_D (a int, b int); +create table test_S (a int, b int); +insert into test_D values(generate_series(6,10),1); +insert into test_S values(generate_series(1,10),2); +merge into test_D using test_S on(test_D.a=test_S.a) when matched then update set test_D.b=test_S.b; +select * from test_D order by a; +truncate table test_S; +insert into test_S values(generate_series(1,10),20); +merge into test_D d using test_S on(d.a=test_S.a) when matched then update set d.b=test_S.b; +select * from test_D order by a; +drop table test_D; +drop table test_S; + +create table test_D(a int[3],b int); +create table test_S(a int[3],b int); +insert into test_D values('{1,2,3}',4); +insert into test_S values('{10,20,30}',4); +merge into test_D using test_S on(test_D.b=test_S.b) when matched then update set test_D.a=test_S.a; +select * from test_D; +truncate table test_S; +insert into test_S values('{11,21,31}',4); +merge into test_D d using test_S on(d.b=test_S.b) when matched then update set d.a=test_S.a; +select * from test_D; +--must compatible with previous features, though not perfect +merge into test_D using test_S on(test_D.b=test_S.b) when matched then update set test_D.a[1,3]=test_S.a[1,3]; +select * from test_D; +merge into test_D d using test_S on(d.b=test_S.b) when matched then update set d.a[1,3]=test_S.a[1,3]; +select * from test_D; +drop table test_D; +drop table test_S; + +create type newtype as(a int,b int); +create table test_D(a newtype, b int); +create table test_S(a newtype, b int); +insert into test_D values(ROW(1,2),3); +insert into test_S values(ROW(10,20),3); +merge into test_D using test_S on(test_D.b=test_S.b) when matched then update set test_D.a=test_S.a; +select * from test_D; +truncate table test_S; +insert into test_S values(ROW(11,12),3); +merge into test_D d using test_S on(d.b=test_S.b) when matched then update set d.a=test_S.a; +select * from test_D; +truncate table test_S; +insert into test_S values(ROW(22,22),3); +merge into test_D a using test_S on(a.b=test_S.b) when matched then update set a.a=21; +merge into test_D a using test_S on(a.b=test_S.b) when matched then update set a.b=22; +select * from test_D; +--fail +merge into test_D a using test_S on(a.b=test_S.b) when matched then update set a.a=test_S.a; +--must compatible with previous features, though not perfect +merge into test_D using test_S on(test_D.b=test_S.b) when matched then update set test_D.a.a=test_S.b; +select * from test_D; +merge into test_D d using test_S on(d.b=test_S.b) when matched then update set d.a.a=test_S.b; +select * from test_D; +drop table test_S; +drop table test_D; +drop type newtype; + +-- Test update multiple entries for the same column with subselect +create table Test (a int[2], b int); +insert into Test values('{1,2}',3); +update Test set (a[1],a[2])=(select 10,20); +select * from Test; +drop table Test; +create type nt as(a int,b int); +create table Test(a nt,b nt,c int); +insert into Test values(row(1,2),row(3,4),5); +update Test set (a.b,b.b)=(select 20,40); +select * from Test; +drop table Test; +drop type nt; + +-- Test comment in subselect of update +create table Test(a int,b int); +insert into Test values(1,2); +update Test set (a)=(select /*comment*/10); +select * from Test; +update Test set (a)=(select /*+comment*/20); +select * from Test; +drop table Test; + +--Test update multiple fields of column which using composite type at once +create type nt as(a int,b int); +create table AA (a nt, b int,c char); +explain (verbose on, costs off) insert into AA values(ROW(1,2),3,'4'); +insert into AA values(ROW(1,2),3,'4'); +explain (verbose on, costs off) update AA set a.a=10,a.b=20 where c='4'; +update AA set a.a=10,a.b=20 where c='4'; +select * from AA; +drop table AA; +drop type nt; + +--Test update multiple values of of an array at once +create table Test (a int[2], b int,c char); +insert into Test values('{1,2}',3,'4'); +explain (verbose on, costs off) update Test set a[1]=100,a[2]=200 where c='4'; +update Test set a[1]=100,a[2]=200 where c='4'; +select * from Test; +explain (verbose on, costs off) update Test set a[1,2]='{101,201}' where c='4'; +update Test set a[1,2]='{101,201}' where c='4'; +select * from Test; +explain (verbose on, costs off) insert into Test (a[1,2],b,c) values('{113,114}',4,'5'); +insert into Test (a[1,2],b,c) values('{113,114}',4,'5'); +select * from Test order by 3; +select a[1,2] from Test where c='4'; +explain (verbose on, costs off) insert into Test (a[1],a[2],b,c)values(1,2,3,'6'); +insert into Test (a[1],a[2],b,c)values(1,2,3,'6'); +select * from Test order by 3; +explain (verbose on, costs off) insert into Test (a[1:2],b,c)values('{1,2}',3,'7'); +insert into Test (a[1:2],b,c)values('{1,2}',3,'7'); +select * from Test order by 3; +explain (verbose on, costs off) update Test set a[1:2]='{10,20}' where c='7'; +update Test set a[1:2]='{10,20}' where c='7'; +select * from Test order by 3; +drop table Test; diff --git a/contrib/dolphin/sql/case_sensitive_test/vacuum.sql b/contrib/dolphin/sql/case_sensitive_test/vacuum.sql new file mode 100644 index 0000000000000000000000000000000000000000..eef6010f4343285080aa396661c6c1cdb6109361 --- /dev/null +++ b/contrib/dolphin/sql/case_sensitive_test/vacuum.sql @@ -0,0 +1,64 @@ +\c table_name_test_db; +SET lower_case_table_names TO 0; +-- +-- VACUUM +-- +CREATE TABLE Vactst (i INT); +INSERT INTO Vactst VALUES (1); +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst VALUES (0); +SELECT count(*) FROM Vactst; +DELETE FROM Vactst WHERE i != 0; +SELECT * FROM Vactst; +VACUUM FULL Vactst; +UPDATE Vactst SET i = i + 1; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst SELECT * FROM Vactst; +INSERT INTO Vactst VALUES (0); +SELECT count(*) FROM Vactst; +DELETE FROM Vactst WHERE i != 0; +VACUUM (FULL) Vactst; +DELETE FROM Vactst; +SELECT * FROM Vactst; + +VACUUM (FULL, FREEZE) Vactst; +VACUUM (ANALYZE, FULL) Vactst; + +CREATE TABLE Vaccluster (i INT PRIMARY KEY); +ALTER TABLE Vaccluster CLUSTER ON Vaccluster_pkey; +INSERT INTO Vaccluster SELECT * FROM Vactst; +CLUSTER Vaccluster; + +set xc_maintenance_mode = on; +VACUUM FULL pg_am; +VACUUM FULL pg_class; +VACUUM FULL pg_database; +set xc_maintenance_mode = off; +VACUUM FULL Vaccluster; +VACUUM FULL Vactst; + +DROP TABLE Vaccluster; +DROP TABLE Vactst; + +CREATE TABLE "~!@#$%^&*+-=`,./\';:{}[]|0(>_<)0"(A TEXT); +VACUUM "~!@#$%^&*+-=`,./\';:{}[]|0(>_<)0"; +DROP TABLE "~!@#$%^&*+-=`,./\';:{}[]|0(>_<)0";