-- =================================================================== -- create FDW objects -- =================================================================== --Testcase 483: CREATE EXTENSION sqlite_fdw; DO $d$ BEGIN EXECUTE $$CREATE SERVER sqlite_svr FOREIGN DATA WRAPPER sqlite_fdw OPTIONS (database '/tmp/sqlitefdw_test_post.db')$$; EXECUTE $$CREATE SERVER sqlite_svr2 FOREIGN DATA WRAPPER sqlite_fdw OPTIONS (database '/tmp/sqlitefdw_test_post.db')$$; EXECUTE $$CREATE SERVER sqlite_svr3 FOREIGN DATA WRAPPER sqlite_fdw OPTIONS (database '/tmp/sqlitefdw_test_post.db')$$; END; $d$; --Testcase 484: CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 485: CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; CREATE USER MAPPING FOR public SERVER sqlite_svr3; -- =================================================================== -- create objects used through FDW sqlite server -- =================================================================== --Testcase 486: CREATE SCHEMA "S 1"; IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO "S 1"; --Testcase 1: INSERT INTO "S 1"."T 1" SELECT id, id % 10, to_char(id, 'FM00000'), '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval, '1970-01-01'::timestamp + ((id % 100) || ' days')::interval, id % 10, id % 10, 'foo' FROM generate_series(1, 1000) id; --Testcase 2: INSERT INTO "S 1"."T 2" SELECT id, 'AAA' || to_char(id, 'FM000') FROM generate_series(1, 100) id; --Testcase 3: INSERT INTO "S 1"."T 3" SELECT id, id + 1, 'AAA' || to_char(id, 'FM000') FROM generate_series(1, 100) id; --Testcase 487: DELETE FROM "S 1"."T 3" WHERE c1 % 2 != 0; -- delete for outer join tests --Testcase 4: INSERT INTO "S 1"."T 4" SELECT id, id + 1, 'AAA' || to_char(id, 'FM000') FROM generate_series(1, 100) id; --Testcase 488: DELETE FROM "S 1"."T 4" WHERE c1 % 3 != 0; -- delete for outer join tests /*ANALYZE "S 1"."T 1"; ANALYZE "S 1"."T 2"; ANALYZE "S 1"."T 3"; ANALYZE "S 1"."T 4";*/ -- =================================================================== -- create foreign tables -- =================================================================== --Testcase 489: CREATE FOREIGN TABLE ft1 ( c0 int, c1 int OPTIONS (key 'true'), c2 int NOT NULL, c3 text, c4 timestamptz, c5 timestamp, c6 varchar(10), c7 char(10) default 'ft1', c8 text ) SERVER sqlite_svr; ALTER FOREIGN TABLE ft1 DROP COLUMN c0; --Testcase 490: CREATE FOREIGN TABLE ft2 ( c1 int OPTIONS (key 'true'), c2 int NOT NULL, cx int, c3 text, c4 timestamptz, c5 timestamp, c6 varchar(10), c7 char(10) default 'ft2', c8 text ) SERVER sqlite_svr; ALTER FOREIGN TABLE ft2 DROP COLUMN cx; --Testcase 491: CREATE FOREIGN TABLE ft4 ( c1 int NOT NULL, c2 int NOT NULL, c3 text ) SERVER sqlite_svr OPTIONS (table 'T 3'); --Testcase 492: CREATE FOREIGN TABLE ft5 ( c1 int OPTIONS (key 'true'), c2 int NOT NULL, c3 text ) SERVER sqlite_svr OPTIONS (table 'T 4'); --Testcase 493: CREATE FOREIGN TABLE ft6 ( c1 int NOT NULL, c2 int NOT NULL, c3 text ) SERVER sqlite_svr2 OPTIONS (table 'T 4'); CREATE FOREIGN TABLE ft7 ( c1 int NOT NULL, c2 int NOT NULL, c3 text ) SERVER sqlite_svr3 OPTIONS (table 'T 4'); ALTER FOREIGN TABLE ft1 OPTIONS (table 'T 1'); ALTER FOREIGN TABLE ft2 OPTIONS (table 'T 1'); ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1'); --Testcase 5: \det+ List of foreign tables Schema | Table | Server | FDW options | Description --------+-------+-------------+-----------------+------------- public | ft1 | sqlite_svr | ("table" 'T 1') | public | ft2 | sqlite_svr | ("table" 'T 1') | public | ft4 | sqlite_svr | ("table" 'T 3') | public | ft5 | sqlite_svr | ("table" 'T 4') | public | ft6 | sqlite_svr2 | ("table" 'T 4') | public | ft7 | sqlite_svr3 | ("table" 'T 4') | (6 rows) -- Test that alteration of server options causes reconnection -- Remote's errors might be non-English, so hide them to ensure stable results \set VERBOSITY terse --Testcase 6: SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work c3 | c4 -------+------------------------------ 00001 | Fri Jan 02 00:00:00 1970 PST (1 row) ALTER SERVER sqlite_svr OPTIONS (SET database 'no such database'); --Testcase 7: SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should fail ERROR: SQL error during prepare: no such table: main.T 1 SELECT `C 1`, `c3`, `c4` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST LIMIT 1 DO $d$ BEGIN EXECUTE $$ALTER SERVER sqlite_svr OPTIONS (SET database '/tmp/sqlitefdw_test_post.db')$$; END; $d$; --Testcase 8: SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work again c3 | c4 -------+------------------------------ 00001 | Fri Jan 02 00:00:00 1970 PST (1 row) \set VERBOSITY default -- Now we should be able to run ANALYZE. -- To exercise multiple code paths, we use local stats on ft1 -- and remote-estimate mode on ft2. --ANALYZE ft1; --ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true'); -- =================================================================== -- simple queries -- =================================================================== -- single table without alias --Testcase 9: EXPLAIN (COSTS OFF) SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10; QUERY PLAN --------------------- Foreign Scan on ft1 (1 row) --Testcase 10: SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo 103 | 3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo 105 | 5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 107 | 7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 109 | 9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo (10 rows) -- single table with alias - also test that tableoid sort is not pushed to remote side --Testcase 11: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------------------------------- Limit Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid -> Sort Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid Sort Key: t1.c3, t1.c1, t1.tableoid -> Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (8 rows) --Testcase 12: SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo 103 | 3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo 105 | 5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 107 | 7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 109 | 9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo (10 rows) -- whole-row reference --Testcase 13: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: t1.*, c3, c1 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 (3 rows) --Testcase 14: SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; t1 -------------------------------------------------------------------------------------------- (101,1,00101,"Fri Jan 02 00:00:00 1970 PST","Fri Jan 02 00:00:00 1970",1,"1 ",foo) (102,2,00102,"Sat Jan 03 00:00:00 1970 PST","Sat Jan 03 00:00:00 1970",2,"2 ",foo) (103,3,00103,"Sun Jan 04 00:00:00 1970 PST","Sun Jan 04 00:00:00 1970",3,"3 ",foo) (104,4,00104,"Mon Jan 05 00:00:00 1970 PST","Mon Jan 05 00:00:00 1970",4,"4 ",foo) (105,5,00105,"Tue Jan 06 00:00:00 1970 PST","Tue Jan 06 00:00:00 1970",5,"5 ",foo) (106,6,00106,"Wed Jan 07 00:00:00 1970 PST","Wed Jan 07 00:00:00 1970",6,"6 ",foo) (107,7,00107,"Thu Jan 08 00:00:00 1970 PST","Thu Jan 08 00:00:00 1970",7,"7 ",foo) (108,8,00108,"Fri Jan 09 00:00:00 1970 PST","Fri Jan 09 00:00:00 1970",8,"8 ",foo) (109,9,00109,"Sat Jan 10 00:00:00 1970 PST","Sat Jan 10 00:00:00 1970",9,"9 ",foo) (110,0,00110,"Sun Jan 11 00:00:00 1970 PST","Sun Jan 11 00:00:00 1970",0,"0 ",foo) (10 rows) -- empty result --Testcase 15: SELECT * FROM ft1 WHERE false; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+----+----+----+----+----+---- (0 rows) -- with WHERE clause --Testcase 16: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c7` >= '1')) AND ((`C 1` = 101)) AND ((`c6` = '1')) (3 rows) --Testcase 17: SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1'; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo (1 row) -- with FOR UPDATE/SHARE --Testcase 18: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE; QUERY PLAN -------------------------------------------------------------------------------------------------------------------- LockRows Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* -> Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 101)) (5 rows) --Testcase 19: SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo (1 row) --Testcase 20: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE; QUERY PLAN -------------------------------------------------------------------------------------------------------------------- LockRows Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* -> Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 102)) (5 rows) --Testcase 21: SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo (1 row) -- aggregate --Testcase 22: SELECT COUNT(*) FROM ft1 t1; count ------- 1000 (1 row) -- subquery --Testcase 23: SELECT * FROM ft1 t1 WHERE t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 <= 10) ORDER BY c1; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo (10 rows) -- subquery+MAX --Testcase 24: SELECT * FROM ft1 t1 WHERE t1.c3 = (SELECT MAX(c3) FROM ft2 t2) ORDER BY c1; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+----+-------+------------------------------+--------------------------+----+------------+----- 1000 | 0 | 01000 | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0 | 0 | foo (1 row) -- used in CTE --Testcase 25: WITH t1 AS (SELECT * FROM ft1 WHERE c1 <= 10) SELECT t2.c1, t2.c2, t2.c3, t2.c4 FROM t1, ft2 t2 WHERE t1.c1 = t2.c1 ORDER BY t1.c1; c1 | c2 | c3 | c4 ----+----+-------+------------------------------ 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST (10 rows) -- fixed values --Testcase 26: SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1; ?column? | ?column? ----------+---------- fixed | (1 row) -- Test forcing the remote server to produce sorted data for a merge join. SET enable_hashjoin TO false; SET enable_nestloop TO false; -- inner join; expressions in the clauses appear in the equivalence class list --Testcase 27: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------ Foreign Scan Output: t1.c1, t2."C 1" SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 100 (3 rows) --Testcase 28: SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; c1 | C 1 -----+----- 101 | 101 102 | 102 103 | 103 104 | 104 105 | 105 106 | 106 107 | 107 108 | 108 109 | 109 110 | 110 (10 rows) -- outer join; expressions in the clauses do not appear in equivalence class -- list but no output change as compared to the previous query --Testcase 29: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1.c1, t2."C 1" SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 100 (3 rows) --Testcase 30: SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10; c1 | C 1 -----+----- 101 | 101 102 | 102 103 | 103 104 | 104 105 | 105 106 | 106 107 | 107 108 | 108 109 | 109 110 | 110 (10 rows) -- A join between local table and foreign join. ORDER BY clause is added to the -- foreign join so that the local table can be joined using merge join strategy. --Testcase 31: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1."C 1" SQLite query: SELECT r1.`C 1` FROM (main."T 1" r1 LEFT JOIN (main."T 1" r2 INNER JOIN main."T 1" r3 ON (((r2.`C 1` = r3.`C 1`)))) ON (((r3.`C 1` = r1.`C 1`)))) LIMIT 10 OFFSET 100 (3 rows) --Testcase 32: SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; C 1 ----- 101 102 103 104 105 106 107 108 109 110 (10 rows) -- Test similar to above, except that the full join prevents any equivalence -- classes from being merged. This produces single relation equivalence classes -- included in join restrictions. --Testcase 33: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1."C 1", t2.c1, t3.c1 SQLite query: SELECT r1.`C 1`, r2.`C 1`, r3.`C 1` FROM ((main."T 1" r1 LEFT JOIN main."T 1" r3 ON (((r3.`C 1` = r1.`C 1`)))) LEFT JOIN main."T 1" r2 ON (((r2.`C 1` = r3.`C 1`)))) LIMIT 10 OFFSET 100 (3 rows) --Testcase 34: SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; C 1 | c1 | c1 -----+-----+----- 101 | 101 | 101 102 | 102 | 102 103 | 103 | 103 104 | 104 | 104 105 | 105 | 105 106 | 106 | 106 107 | 107 | 107 108 | 108 | 108 109 | 109 | 109 110 | 110 | 110 (10 rows) -- Test similar to above with all full outer joins --Testcase 35: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------- Limit Output: t1."C 1", t2.c1, t3.c1 -> Merge Full Join Output: t1."C 1", t2.c1, t3.c1 Merge Cond: (t1."C 1" = t3.c1) -> Sort Output: t1."C 1" Sort Key: t1."C 1" -> Foreign Scan on "S 1"."T 1" t1 Output: t1."C 1" SQLite query: SELECT `C 1` FROM main."T 1" -> Sort Output: t2.c1, t3.c1 Sort Key: t3.c1 -> Merge Full Join Output: t2.c1, t3.c1 Merge Cond: (t2.c1 = t3.c1) -> Sort Output: t2.c1 Sort Key: t2.c1 -> Foreign Scan on public.ft1 t2 Output: t2.c1 SQLite query: SELECT `C 1` FROM main."T 1" -> Sort Output: t3.c1 Sort Key: t3.c1 -> Foreign Scan on public.ft2 t3 Output: t3.c1 SQLite query: SELECT `C 1` FROM main."T 1" (29 rows) --Testcase 36: SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10; C 1 | c1 | c1 -----+-----+----- 101 | 101 | 101 102 | 102 | 102 103 | 103 | 103 104 | 104 | 104 105 | 105 | 105 106 | 106 | 106 107 | 107 | 107 108 | 108 | 108 109 | 109 | 109 110 | 110 | 110 (10 rows) RESET enable_hashjoin; RESET enable_nestloop; -- Test executing assertion in estimate_path_cost_size() that makes sure that -- retrieved_rows for foreign rel re-used to cost pre-sorted foreign paths is -- a sensible value even when the rel has tuples=0 -- CREATE TABLE loct_empty (c1 int NOT NULL, c2 text); CREATE FOREIGN TABLE ft_empty (c1 int NOT NULL, c2 text) SERVER sqlite_svr OPTIONS (table 'loct_empty'); INSERT INTO "S 1".loct_empty SELECT id, 'AAA' || to_char(id, 'FM000') FROM generate_series(1, 100) id; DELETE FROM "S 1".loct_empty; -- ANALYZE ft_empty; EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1; QUERY PLAN --------------------------------------------------------------------------------------- Foreign Scan on public.ft_empty Output: c1, c2 SQLite query: SELECT `c1`, `c2` FROM main."loct_empty" ORDER BY `c1` ASC NULLS LAST (3 rows) -- =================================================================== -- WHERE with remotely-executable conditions -- =================================================================== --Testcase 37: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 1; -- Var, OpExpr(b), Const QUERY PLAN ------------------------------------------------------------------------------------------------------------ Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) (3 rows) --Testcase 38: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 100 AND t1.c2 = 0; -- BoolExpr QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 100)) AND ((`c2` = 0)) (3 rows) --Testcase 39: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NULL; -- NullTest QUERY PLAN ---------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` IS NULL)) (3 rows) --Testcase 40: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL; -- NullTest QUERY PLAN -------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` IS NOT NULL)) (3 rows) --Testcase 41: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((round(abs(`C 1`), 0) = 1)) (3 rows) --Testcase 42: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l) QUERY PLAN -------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = (- `C 1`))) (3 rows) --Testcase 44: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr QUERY PLAN ---------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 Filter: ((t1.c1 IS NOT NULL) IS DISTINCT FROM (t1.c1 IS NOT NULL)) SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (4 rows) --Testcase 45: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (`C 1` IN (`c2`, 1, (`C 1` + 0))) (3 rows) --Testcase 46: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- SubscriptingRef QUERY PLAN ---------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 Filter: (t1.c1 = (ARRAY[t1.c1, t1.c2, 3])[1]) SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (4 rows) --Testcase 47: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar'; -- check special chars QUERY PLAN ----------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c6` = 'foo''s\\bar')) (3 rows) --Testcase 48: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c8 = 'foo'; -- can't be sent to remote QUERY PLAN --------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) (3 rows) -- parameterized remote path for foreign table --Testcase 49: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: a."C 1", a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8, b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8 SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, r2.`C 1`, r2.`c2`, r2.`c3`, r2.`c4`, r2.`c5`, r2.`c6`, r2.`c7`, r2.`c8` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`c2` = r2.`C 1`)) AND ((r1.`C 1` = 47)))) (3 rows) --Testcase 50: SELECT * FROM ft2 a, ft2 b WHERE a.c1 = 47 AND b.c1 = a.c2; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+----- 47 | 7 | 00047 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo | 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo (1 row) -- check both safe and unsafe join conditions --Testcase 51: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft2 a, ft2 b WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7); QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Foreign Scan Output: a.c1, a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8, b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8 Filter: (upper((a.c7)::text) = (b.c7)::text) SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, r2.`C 1`, r2.`c2`, r2.`c3`, r2.`c4`, r2.`c5`, r2.`c6`, r2.`c7`, r2.`c8` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`c2` = 6)) AND ((r1.`c8` = 'foo')))) (4 rows) --Testcase 52: SELECT * FROM ft2 a, ft2 b WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7); c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+-----+-----+----+-------+------------------------------+--------------------------+----+------------+----- 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo (100 rows) -- bug before 9.3.5 due to sloppy handling of remote-estimate parameters --Testcase 53: SELECT * FROM ft1 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft2 WHERE c1 < 5)); c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo (4 rows) --Testcase 54: SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5)); c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo (4 rows) -- we should not push order by clause with volatile expressions or unsafe -- collations --Testcase 55: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft2 ORDER BY ft2.c1, random(); QUERY PLAN ---------------------------------------------------------------------------------------------- Sort Output: c1, c2, c3, c4, c5, c6, c7, c8, (random()) Sort Key: ft2.c1, (random()) -> Foreign Scan on public.ft2 Output: c1, c2, c3, c4, c5, c6, c7, c8, random() SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (6 rows) --Testcase 56: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C"; QUERY PLAN ---------------------------------------------------------------------------------------------- Sort Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text) Sort Key: ft2.c1, ft2.c3 COLLATE "C" -> Foreign Scan on public.ft2 Output: c1, c2, c3, c4, c5, c6, c7, c8, c3 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (6 rows) -- user-defined operator/function --Testcase 494: CREATE FUNCTION sqlite_fdw_abs(int) RETURNS int AS $$ BEGIN RETURN abs($1); END $$ LANGUAGE plpgsql IMMUTABLE; --Testcase 495: CREATE OPERATOR === ( LEFTARG = int, RIGHTARG = int, PROCEDURE = int4eq, COMMUTATOR = === ); -- built-in operators and functions can be shipped for remote execution --Testcase 57: EXPLAIN (VERBOSE, COSTS OFF) SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2); QUERY PLAN -------------------------------------------------------------------------------- Foreign Scan Output: (count(c3)) SQLite query: SELECT count(`c3`) FROM main."T 1" WHERE ((`C 1` = abs(`c2`))) (3 rows) --Testcase 58: SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2); count ------- 9 (1 row) --Testcase 59: EXPLAIN (VERBOSE, COSTS OFF) SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2; QUERY PLAN --------------------------------------------------------------------------- Foreign Scan Output: (count(c3)) SQLite query: SELECT count(`c3`) FROM main."T 1" WHERE ((`C 1` = `c2`)) (3 rows) --Testcase 60: SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2; count ------- 9 (1 row) -- by default, user-defined ones cannot --Testcase 61: EXPLAIN (VERBOSE, COSTS OFF) SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); QUERY PLAN ---------------------------------------------------------------- Aggregate Output: count(c3) -> Foreign Scan on public.ft1 t1 Output: c3 Filter: (t1.c1 = sqlite_fdw_abs(t1.c2)) SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" (6 rows) --Testcase 62: SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); count ------- 9 (1 row) --Testcase 63: EXPLAIN (VERBOSE, COSTS OFF) SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; QUERY PLAN ---------------------------------------------------------------- Aggregate Output: count(c3) -> Foreign Scan on public.ft1 t1 Output: c3 Filter: (t1.c1 === t1.c2) SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" (6 rows) --Testcase 64: SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; count ------- 9 (1 row) -- ORDER BY can be shipped, though --Testcase 496: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- Limit Output: c1, c2, c3, c4, c5, c6, c7, c8 -> Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 Filter: (t1.c1 === t1.c2) SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST (6 rows) --Testcase 497: SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo (1 row) -- but let's put them in an extension ... ALTER EXTENSION sqlite_fdw ADD FUNCTION sqlite_fdw_abs(int); ALTER EXTENSION sqlite_fdw ADD OPERATOR === (int, int); --ALTER SERVER sqlite_svr2 OPTIONS (ADD extensions 'sqlite_fdw'); -- ... now they can be shipped --Testcase 498: EXPLAIN (VERBOSE, COSTS OFF) SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); QUERY PLAN ---------------------------------------------------------------- Aggregate Output: count(c3) -> Foreign Scan on public.ft1 t1 Output: c3 Filter: (t1.c1 = sqlite_fdw_abs(t1.c2)) SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" (6 rows) --Testcase 499: SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = sqlite_fdw_abs(t1.c2); count ------- 9 (1 row) --Testcase 500: EXPLAIN (VERBOSE, COSTS OFF) SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; QUERY PLAN ---------------------------------------------------------------- Aggregate Output: count(c3) -> Foreign Scan on public.ft1 t1 Output: c3 Filter: (t1.c1 === t1.c2) SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" (6 rows) --Testcase 501: SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; count ------- 9 (1 row) -- and both ORDER BY and LIMIT can be shipped --Testcase 502: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- Limit Output: c1, c2, c3, c4, c5, c6, c7, c8 -> Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 Filter: (t1.c1 === t1.c2) SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST (6 rows) --Testcase 503: SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo (1 row) -- =================================================================== -- JOIN queries -- =================================================================== -- Analyze ft4 and ft5 so that we have better statistics. These tables do not -- have use_remote_estimate set. --ANALYZE ft4; --ANALYZE ft5; -- join two tables --Testcase 65: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Foreign Scan Output: t1.c1, t2.c1, t1.c3 SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 (3 rows) --Testcase 66: SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; c1 | c1 -----+----- 101 | 101 102 | 102 103 | 103 104 | 104 105 | 105 106 | 106 107 | 107 108 | 108 109 | 109 110 | 110 (10 rows) -- join three tables --Testcase 67: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1.c1, t2.c2, t3.c3, t1.c3 SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3`, r1.`c3` FROM ((main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) INNER JOIN main."T 3" r4 ON (((r1.`C 1` = r4.`c1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 10 (3 rows) --Testcase 68: SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10; c1 | c2 | c3 ----+----+-------- 22 | 2 | AAA022 24 | 4 | AAA024 26 | 6 | AAA026 28 | 8 | AAA028 30 | 0 | AAA030 32 | 2 | AAA032 34 | 4 | AAA034 36 | 6 | AAA036 38 | 8 | AAA038 40 | 0 | AAA040 (10 rows) -- left outer join --Testcase 69: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1.c1, t2.c1 SQLite query: SELECT r1.`c1`, r2.`c1` FROM (main."T 3" r1 LEFT JOIN main."T 4" r2 ON (((r1.`c1` = r2.`c1`)))) ORDER BY r1.`c1` ASC NULLS LAST, r2.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 (3 rows) --Testcase 70: SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; c1 | c1 ----+---- 22 | 24 | 24 26 | 28 | 30 | 30 32 | 34 | 36 | 36 38 | 40 | (10 rows) -- left outer join three tables --Testcase 71: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Foreign Scan Output: t1.c1, t2.c2, t3.c3 SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) LEFT JOIN main."T 3" r4 ON (((r2.`C 1` = r4.`c1`)))) LIMIT 10 OFFSET 10 (3 rows) --Testcase 72: SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; c1 | c2 | c3 ----+----+-------- 11 | 1 | 12 | 2 | AAA012 13 | 3 | 14 | 4 | AAA014 15 | 5 | 16 | 6 | AAA016 17 | 7 | 18 | 8 | AAA018 19 | 9 | 20 | 0 | AAA020 (10 rows) -- left outer join + placement of clauses. -- clauses within the nullable side are not pulled up, but top level clause on -- non-nullable side is pushed into non-nullable side --Testcase 73: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10; QUERY PLAN ----------------------------------------------------------------------------------- Hash Left Join Output: t1.c1, t1.c2, ft5.c1, ft5.c2 Hash Cond: (t1.c1 = ft5.c1) -> Foreign Scan on public.ft4 t1 Output: t1.c1, t1.c2, t1.c3 SQLite query: SELECT `c1`, `c2` FROM main."T 3" WHERE ((`c1` < 10)) -> Hash Output: ft5.c1, ft5.c2 -> Foreign Scan on public.ft5 Output: ft5.c1, ft5.c2 SQLite query: SELECT `c1`, `c2` FROM main."T 4" WHERE ((`c1` < 10)) (11 rows) --Testcase 74: SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10; c1 | c2 | c1 | c2 ----+----+----+---- 2 | 3 | | 4 | 5 | | 6 | 7 | 6 | 7 8 | 9 | | (4 rows) -- clauses within the nullable side are not pulled up, but the top level clause -- on nullable side is not pushed down into nullable side --Testcase 75: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10; QUERY PLAN ----------------------------------------------------------------------------------- Hash Left Join Output: t1.c1, t1.c2, ft5.c1, ft5.c2 Hash Cond: (t1.c1 = ft5.c1) Filter: ((ft5.c1 < 10) OR (ft5.c1 IS NULL)) -> Foreign Scan on public.ft4 t1 Output: t1.c1, t1.c2, t1.c3 SQLite query: SELECT `c1`, `c2` FROM main."T 3" WHERE ((`c1` < 10)) -> Hash Output: ft5.c1, ft5.c2 -> Foreign Scan on public.ft5 Output: ft5.c1, ft5.c2 SQLite query: SELECT `c1`, `c2` FROM main."T 4" WHERE ((`c1` < 10)) (12 rows) --Testcase 76: SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10; c1 | c2 | c1 | c2 ----+----+----+---- 2 | 3 | | 4 | 5 | | 6 | 7 | 6 | 7 8 | 9 | | (4 rows) -- right outer join --Testcase 77: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1.c1, t2.c1 SQLite query: SELECT r1.`c1`, r2.`c1` FROM (main."T 3" r2 LEFT JOIN main."T 4" r1 ON (((r1.`c1` = r2.`c1`)))) ORDER BY r2.`c1` ASC NULLS LAST, r1.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 (3 rows) --Testcase 78: SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10; c1 | c1 ----+---- | 22 24 | 24 | 26 | 28 30 | 30 | 32 | 34 36 | 36 | 38 | 40 (10 rows) -- right outer join three tables --Testcase 79: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Foreign Scan Output: t1.c1, t2.c2, t3.c3 SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 3" r4 LEFT JOIN main."T 1" r2 ON (((r2.`C 1` = r4.`c1`)))) LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 10 (3 rows) --Testcase 80: SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; c1 | c2 | c3 ----+----+-------- 22 | 2 | AAA022 24 | 4 | AAA024 26 | 6 | AAA026 28 | 8 | AAA028 30 | 0 | AAA030 32 | 2 | AAA032 34 | 4 | AAA034 36 | 6 | AAA036 38 | 8 | AAA038 40 | 0 | AAA040 (10 rows) -- full outer join --Testcase 81: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10; QUERY PLAN --------------------------------------------------------------------- Limit Output: t1.c1, t2.c1 -> Sort Output: t1.c1, t2.c1 Sort Key: t1.c1, t2.c1 -> Merge Full Join Output: t1.c1, t2.c1 Merge Cond: (t1.c1 = t2.c1) -> Sort Output: t1.c1 Sort Key: t1.c1 -> Foreign Scan on public.ft4 t1 Output: t1.c1 SQLite query: SELECT `c1` FROM main."T 3" -> Sort Output: t2.c1 Sort Key: t2.c1 -> Foreign Scan on public.ft5 t2 Output: t2.c1 SQLite query: SELECT `c1` FROM main."T 4" (20 rows) --Testcase 82: SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10; c1 | c1 -----+---- 92 | 94 | 96 | 96 98 | 100 | | 3 | 9 | 15 | 21 | 27 (10 rows) -- full outer join with restrictions on the joining relations -- a. the joining relations are both base relations --Testcase 83: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1; QUERY PLAN ------------------------------------------------------------------------------------------------------- Sort Output: ft4.c1, ft5.c1 Sort Key: ft4.c1, ft5.c1 -> Hash Full Join Output: ft4.c1, ft5.c1 Hash Cond: (ft4.c1 = ft5.c1) -> Foreign Scan on public.ft4 Output: ft4.c1, ft4.c2, ft4.c3 SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -> Hash Output: ft5.c1 -> Foreign Scan on public.ft5 Output: ft5.c1 SQLite query: SELECT `c1` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) (14 rows) --Testcase 84: SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1; c1 | c1 ----+---- 50 | 52 | 54 | 54 56 | 58 | 60 | 60 | 51 | 57 (8 rows) --Testcase 85: EXPLAIN (VERBOSE, COSTS OFF) SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------------------------------------- Limit Output: 1 -> Merge Full Join Output: 1 -> Foreign Scan on public.ft4 Output: ft4.c1, ft4.c2, ft4.c3 SQLite query: SELECT NULL FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -> Materialize Output: ft5.c1, ft5.c2, ft5.c3 -> Foreign Scan on public.ft5 Output: ft5.c1, ft5.c2, ft5.c3 SQLite query: SELECT NULL FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) (12 rows) --Testcase 86: SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10; ?column? ---------- 1 1 1 1 1 1 1 1 1 1 (10 rows) -- b. one of the joining relations is a base relation and the other is a join -- relation --Testcase 87: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Sort Output: ft4.c1, t2.c1, t3.c1 Sort Key: ft4.c1, t2.c1, t3.c1 -> Hash Full Join Output: ft4.c1, t2.c1, t3.c1 Hash Cond: (t2.c1 = ft4.c1) -> Foreign Scan Output: t2.c1, t3.c1 SQLite query: SELECT r5.`c1`, r6.`c1` FROM (main."T 3" r5 LEFT JOIN main."T 4" r6 ON (((r5.`c1` = r6.`c1`)))) WHERE ((r5.`c1` >= 50)) AND ((r5.`c1` <= 60)) -> Hash Output: ft4.c1 -> Foreign Scan on public.ft4 Output: ft4.c1 SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) (14 rows) --Testcase 88: SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; c1 | a | b ----+----+---- 50 | 50 | 52 | 52 | 54 | 54 | 54 56 | 56 | 58 | 58 | 60 | 60 | 60 (6 rows) -- c. test deparsing the remote query as nested subqueries --Testcase 89: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; QUERY PLAN ------------------------------------------------------------------------------------------------------------- Sort Output: ft4.c1, ft4_1.c1, ft5.c1 Sort Key: ft4.c1, ft4_1.c1, ft5.c1 -> Hash Full Join Output: ft4.c1, ft4_1.c1, ft5.c1 Hash Cond: (ft4_1.c1 = ft4.c1) -> Hash Full Join Output: ft4_1.c1, ft5.c1 Hash Cond: (ft4_1.c1 = ft5.c1) Filter: ((ft4_1.c1 IS NULL) OR (ft4_1.c1 IS NOT NULL)) -> Foreign Scan on public.ft4 ft4_1 Output: ft4_1.c1, ft4_1.c2, ft4_1.c3 SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -> Hash Output: ft5.c1 -> Foreign Scan on public.ft5 Output: ft5.c1 SQLite query: SELECT `c1` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -> Hash Output: ft4.c1 -> Foreign Scan on public.ft4 Output: ft4.c1 SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) (23 rows) --Testcase 90: SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b; c1 | a | b ----+----+---- 50 | 50 | 52 | 52 | 54 | 54 | 54 56 | 56 | 58 | 58 | 60 | 60 | 60 | | 51 | | 57 (8 rows) -- d. test deparsing rowmarked relations as subqueries --Testcase 91: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------- LockRows Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".*, ft4.*, ft5.* -> Sort Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".*, ft4.*, ft5.* Sort Key: ft4.c1, ft5.c1 -> Nested Loop Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".*, ft4.*, ft5.* -> Foreign Scan on "S 1"."T 3" Output: "T 3".c1, "T 3".* SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" WHERE ((`c1` = 50)) -> Materialize Output: ft4.c1, ft4.*, ft5.c1, ft5.* -> Merge Full Join Output: ft4.c1, ft4.*, ft5.c1, ft5.* Merge Cond: (ft4.c1 = ft5.c1) Filter: ((ft4.c1 IS NULL) OR (ft4.c1 IS NOT NULL)) -> Sort Output: ft4.c1, ft4.* Sort Key: ft4.c1 -> Foreign Scan on public.ft4 Output: ft4.c1, ft4.* SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -> Sort Output: ft5.c1, ft5.* Sort Key: ft5.c1 -> Foreign Scan on public.ft5 Output: ft5.c1, ft5.* SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) (28 rows) --Testcase 92: SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1; c1 | a | b ----+----+---- 50 | 50 | 50 | 52 | 50 | 54 | 54 50 | 56 | 50 | 58 | 50 | 60 | 60 50 | | 51 50 | | 57 (8 rows) -- full outer join + inner join --Testcase 93: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit Output: t1.c1, t2.c1, t3.c1 -> Sort Output: t1.c1, t2.c1, t3.c1 Sort Key: t1.c1, t2.c1, t3.c1 -> Hash Full Join Output: t1.c1, t2.c1, t3.c1 Hash Cond: (t3.c1 = t2.c1) -> Foreign Scan on public.ft4 t3 Output: t3.c1, t3.c2, t3.c3 SQLite query: SELECT `c1` FROM main."T 3" -> Hash Output: t1.c1, t2.c1 -> Foreign Scan Output: t1.c1, t2.c1 SQLite query: SELECT r1.`c1`, r2.`c1` FROM (main."T 3" r1 INNER JOIN main."T 4" r2 ON (((r1.`c1` = (r2.`c1` + 1))) AND ((r1.`c1` >= 50)) AND ((r1.`c1` <= 60)))) (16 rows) --Testcase 94: SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10; c1 | c1 | c1 ----+----+---- 52 | 51 | 58 | 57 | | | 2 | | 4 | | 6 | | 8 | | 10 | | 12 | | 14 | | 16 (10 rows) -- full outer join three tables --Testcase 95: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------- Limit Output: t1.c1, t2.c2, t3.c3 -> Hash Full Join Output: t1.c1, t2.c2, t3.c3 Hash Cond: (t2.c1 = t3.c1) -> Hash Full Join Output: t1.c1, t2.c2, t2.c1 Hash Cond: (t1.c1 = t2.c1) -> Foreign Scan on public.ft2 t1 Output: t1.c1 SQLite query: SELECT `C 1` FROM main."T 1" -> Hash Output: t2.c2, t2.c1 -> Foreign Scan on public.ft2 t2 Output: t2.c2, t2.c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" -> Hash Output: t3.c3, t3.c1 -> Foreign Scan on public.ft4 t3 Output: t3.c3, t3.c1 SQLite query: SELECT `c1`, `c3` FROM main."T 3" (21 rows) --Testcase 96: SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; c1 | c2 | c3 ----+----+-------- 11 | 1 | 12 | 2 | AAA012 13 | 3 | 14 | 4 | AAA014 15 | 5 | 16 | 6 | AAA016 17 | 7 | 18 | 8 | AAA018 19 | 9 | 20 | 0 | AAA020 (10 rows) -- full outer join + right outer join --Testcase 97: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Foreign Scan Output: t1.c1, t2.c2, t3.c3 SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 3" r4 LEFT JOIN main."T 1" r2 ON (((r2.`C 1` = r4.`c1`)))) LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) LIMIT 10 OFFSET 10 (3 rows) --Testcase 98: SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; c1 | c2 | c3 ----+----+-------- 22 | 2 | AAA022 24 | 4 | AAA024 26 | 6 | AAA026 28 | 8 | AAA028 30 | 0 | AAA030 32 | 2 | AAA032 34 | 4 | AAA034 36 | 6 | AAA036 38 | 8 | AAA038 40 | 0 | AAA040 (10 rows) -- right outer join + full outer join --Testcase 99: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------- Limit Output: t1.c1, t2.c2, t3.c3 -> Hash Full Join Output: t1.c1, t2.c2, t3.c3 Hash Cond: (t2.c1 = t3.c1) -> Nested Loop Left Join Output: t2.c2, t2.c1, t1.c1 Join Filter: (t1.c1 = t2.c1) -> Foreign Scan on public.ft2 t2 Output: t2.c2, t2.c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" -> Materialize Output: t1.c1 -> Foreign Scan on public.ft2 t1 Output: t1.c1 SQLite query: SELECT `C 1` FROM main."T 1" -> Hash Output: t3.c3, t3.c1 -> Foreign Scan on public.ft4 t3 Output: t3.c3, t3.c1 SQLite query: SELECT `c1`, `c3` FROM main."T 3" (21 rows) --Testcase 100: SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; c1 | c2 | c3 ----+----+-------- 11 | 1 | 12 | 2 | AAA012 13 | 3 | 14 | 4 | AAA014 15 | 5 | 16 | 6 | AAA016 17 | 7 | 18 | 8 | AAA018 19 | 9 | 20 | 0 | AAA020 (10 rows) -- full outer join + left outer join --Testcase 101: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------- Limit Output: t1.c1, t2.c2, t3.c3 -> Nested Loop Left Join Output: t1.c1, t2.c2, t3.c3 Join Filter: (t2.c1 = t3.c1) -> Hash Full Join Output: t1.c1, t2.c2, t2.c1 Hash Cond: (t1.c1 = t2.c1) -> Foreign Scan on public.ft2 t1 Output: t1.c1 SQLite query: SELECT `C 1` FROM main."T 1" -> Hash Output: t2.c2, t2.c1 -> Foreign Scan on public.ft2 t2 Output: t2.c2, t2.c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" -> Materialize Output: t3.c3, t3.c1 -> Foreign Scan on public.ft4 t3 Output: t3.c3, t3.c1 SQLite query: SELECT `c1`, `c3` FROM main."T 3" (21 rows) --Testcase 102: SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; c1 | c2 | c3 ----+----+-------- 11 | 1 | 12 | 2 | AAA012 13 | 3 | 14 | 4 | AAA014 15 | 5 | 16 | 6 | AAA016 17 | 7 | 18 | 8 | AAA018 19 | 9 | 20 | 0 | AAA020 (10 rows) -- left outer join + full outer join --Testcase 103: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------- Limit Output: t1.c1, t2.c2, t3.c3 -> Hash Full Join Output: t1.c1, t2.c2, t3.c3 Hash Cond: (t2.c1 = t3.c1) -> Nested Loop Left Join Output: t1.c1, t2.c2, t2.c1 Join Filter: (t1.c1 = t2.c1) -> Foreign Scan on public.ft2 t1 Output: t1.c1 SQLite query: SELECT `C 1` FROM main."T 1" -> Materialize Output: t2.c2, t2.c1 -> Foreign Scan on public.ft2 t2 Output: t2.c2, t2.c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" -> Hash Output: t3.c3, t3.c1 -> Foreign Scan on public.ft4 t3 Output: t3.c3, t3.c1 SQLite query: SELECT `c1`, `c3` FROM main."T 3" (21 rows) --Testcase 104: SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; c1 | c2 | c3 ----+----+-------- 11 | 1 | 12 | 2 | AAA012 13 | 3 | 14 | 4 | AAA014 15 | 5 | 16 | 6 | AAA016 17 | 7 | 18 | 8 | AAA018 19 | 9 | 20 | 0 | AAA020 (10 rows) SET enable_resultcache TO off; -- right outer join + left outer join --Testcase 105: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Foreign Scan Output: t1.c1, t2.c2, t3.c3 SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM ((main."T 1" r2 LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) LEFT JOIN main."T 3" r4 ON (((r2.`C 1` = r4.`c1`)))) LIMIT 10 OFFSET 10 (3 rows) --Testcase 106: SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; c1 | c2 | c3 ----+----+-------- 11 | 1 | 12 | 2 | AAA012 13 | 3 | 14 | 4 | AAA014 15 | 5 | 16 | 6 | AAA016 17 | 7 | 18 | 8 | AAA018 19 | 9 | 20 | 0 | AAA020 (10 rows) RESET enable_resultcache; -- left outer join + right outer join --Testcase 107: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1.c1, t2.c2, t3.c3 SQLite query: SELECT r1.`C 1`, r2.`c2`, r4.`c3` FROM (main."T 3" r4 LEFT JOIN (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ON (((r2.`C 1` = r4.`c1`)))) LIMIT 10 OFFSET 10 (3 rows) --Testcase 108: SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1 OFFSET 10 LIMIT 10; c1 | c2 | c3 ----+----+-------- 22 | 2 | AAA022 24 | 4 | AAA024 26 | 6 | AAA026 28 | 8 | AAA028 30 | 0 | AAA030 32 | 2 | AAA032 34 | 4 | AAA034 36 | 6 | AAA036 38 | 8 | AAA038 40 | 0 | AAA040 (10 rows) -- full outer join + WHERE clause, only matched rows --Testcase 109: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; QUERY PLAN --------------------------------------------------------------------- Limit Output: t1.c1, t2.c1 -> Sort Output: t1.c1, t2.c1 Sort Key: t1.c1, t2.c1 -> Merge Full Join Output: t1.c1, t2.c1 Merge Cond: (t1.c1 = t2.c1) Filter: ((t1.c1 = t2.c1) OR (t1.c1 IS NULL)) -> Sort Output: t1.c1 Sort Key: t1.c1 -> Foreign Scan on public.ft4 t1 Output: t1.c1 SQLite query: SELECT `c1` FROM main."T 3" -> Sort Output: t2.c1 Sort Key: t2.c1 -> Foreign Scan on public.ft5 t2 Output: t2.c1 SQLite query: SELECT `c1` FROM main."T 4" (21 rows) --Testcase 110: SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; c1 | c1 ----+---- 66 | 66 72 | 72 78 | 78 84 | 84 90 | 90 96 | 96 | 3 | 9 | 15 | 21 (10 rows) -- full outer join + WHERE clause with shippable extensions set --Testcase 504: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE sqlite_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------- Limit Output: t1.c1, t2.c2, t1.c3 -> Hash Full Join Output: t1.c1, t2.c2, t1.c3 Hash Cond: (t2.c1 = t1.c1) Filter: (sqlite_fdw_abs(t1.c1) > 0) -> Foreign Scan on public.ft2 t2 Output: t2.c2, t2.c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" -> Hash Output: t1.c1, t1.c3 -> Foreign Scan on public.ft1 t1 Output: t1.c1, t1.c3 SQLite query: SELECT `C 1`, `c3` FROM main."T 1" (14 rows) --ALTER SERVER sqlite_svr2 OPTIONS (DROP extensions); -- full outer join + WHERE clause with shippable extensions not set --Testcase 505: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE sqlite_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------- Limit Output: t1.c1, t2.c2, t1.c3 -> Hash Full Join Output: t1.c1, t2.c2, t1.c3 Hash Cond: (t2.c1 = t1.c1) Filter: (sqlite_fdw_abs(t1.c1) > 0) -> Foreign Scan on public.ft2 t2 Output: t2.c2, t2.c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" -> Hash Output: t1.c1, t1.c3 -> Foreign Scan on public.ft1 t1 Output: t1.c1, t1.c3 SQLite query: SELECT `C 1`, `c3` FROM main."T 1" (14 rows) ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); ERROR: server "loopback" does not exist -- join two tables with FOR UPDATE clause -- tests whole-row reference for row marks --Testcase 111: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* -> LockRows Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* -> Foreign Scan Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST -> Sort Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 -> Hash Join Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* Hash Cond: (t1.c1 = t2.c1) -> Foreign Scan on public.ft1 t1 Output: t1.c1, t1.c3, t1.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST -> Hash Output: t2.c1, t2.* -> Foreign Scan on public.ft2 t2 Output: t2.c1, t2.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (21 rows) --Testcase 112: SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1; c1 | c1 -----+----- 101 | 101 102 | 102 103 | 103 104 | 104 105 | 105 106 | 106 107 | 107 108 | 108 109 | 109 110 | 110 (10 rows) --Testcase 113: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* -> LockRows Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* -> Foreign Scan Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST -> Sort Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 -> Hash Join Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* Hash Cond: (t1.c1 = t2.c1) -> Foreign Scan on public.ft1 t1 Output: t1.c1, t1.c3, t1.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST -> Hash Output: t2.c1, t2.* -> Foreign Scan on public.ft2 t2 Output: t2.c1, t2.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (21 rows) --Testcase 114: SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE; c1 | c1 -----+----- 101 | 101 102 | 102 103 | 103 104 | 104 105 | 105 106 | 106 107 | 107 108 | 108 109 | 109 110 | 110 (10 rows) -- join two tables with FOR SHARE clause --Testcase 115: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* -> LockRows Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* -> Foreign Scan Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST -> Sort Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 -> Hash Join Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* Hash Cond: (t1.c1 = t2.c1) -> Foreign Scan on public.ft1 t1 Output: t1.c1, t1.c3, t1.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST -> Hash Output: t2.c1, t2.* -> Foreign Scan on public.ft2 t2 Output: t2.c1, t2.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (21 rows) --Testcase 116: SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1; c1 | c1 -----+----- 101 | 101 102 | 102 103 | 103 104 | 104 105 | 105 106 | 106 107 | 107 108 | 108 109 | 109 110 | 110 (10 rows) --Testcase 117: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* -> LockRows Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* -> Foreign Scan Output: t1.c1, t2.c1, t1.c3, t1.*, t2.* SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST -> Sort Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* Sort Key: t1.c3 COLLATE "default" USING <, t1.c1 -> Hash Join Output: t1.c1, t1.c3, t1.*, t2.c1, t2.* Hash Cond: (t1.c1 = t2.c1) -> Foreign Scan on public.ft1 t1 Output: t1.c1, t1.c3, t1.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c3` ASC NULLS LAST, `C 1` ASC NULLS LAST -> Hash Output: t2.c1, t2.* -> Foreign Scan on public.ft2 t2 Output: t2.c1, t2.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (21 rows) --Testcase 118: SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE; c1 | c1 -----+----- 101 | 101 102 | 102 103 | 103 104 | 104 105 | 105 106 | 106 107 | 107 108 | 108 109 | 109 110 | 110 (10 rows) -- join in CTE --Testcase 119: EXPLAIN (VERBOSE, COSTS OFF) WITH t (c1_1, c1_3, c2_1) AS MATERIALIZED (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------ Limit Output: t.c1_1, t.c2_1, t.c1_3 CTE t -> Merge Join Output: t1.c1, t1.c3, t2.c1 Merge Cond: (t1.c1 = t2.c1) -> Sort Output: t1.c1, t1.c3 Sort Key: t1.c1 -> Foreign Scan on public.ft1 t1 Output: t1.c1, t1.c3 SQLite query: SELECT `C 1`, `c3` FROM main."T 1" -> Sort Output: t2.c1 Sort Key: t2.c1 -> Foreign Scan on public.ft2 t2 Output: t2.c1 SQLite query: SELECT `C 1` FROM main."T 1" -> Sort Output: t.c1_1, t.c2_1, t.c1_3 Sort Key: t.c1_3, t.c1_1 -> CTE Scan on t Output: t.c1_1, t.c2_1, t.c1_3 (23 rows) --Testcase 120: WITH t (c1_1, c1_3, c2_1) AS MATERIALIZED (SELECT t1.c1, t1.c3, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) SELECT c1_1, c2_1 FROM t ORDER BY c1_3, c1_1 OFFSET 100 LIMIT 10; c1_1 | c2_1 ------+------ 101 | 101 102 | 102 103 | 103 104 | 104 105 | 105 106 | 106 107 | 107 108 | 108 109 | 109 110 | 110 (10 rows) -- ctid with whole-row reference --Testcase 121: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.ctid, t1, t2, t1.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3 SQLite query: SELECT r1.`ctid`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END, r1.`C 1`, r1.`c3` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 (3 rows) -- SEMI JOIN, not pushed down --Testcase 122: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------------------- Limit Output: t1.c1 -> Merge Semi Join Output: t1.c1 Merge Cond: (t1.c1 = t2.c1) -> Foreign Scan on public.ft1 t1 Output: t1.c1 SQLite query: SELECT `C 1` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST -> Foreign Scan on public.ft2 t2 Output: t2.c1 SQLite query: SELECT `C 1` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST (11 rows) --Testcase 123: SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10; c1 ----- 101 102 103 104 105 106 107 108 109 110 (10 rows) -- ANTI JOIN, not pushed down --Testcase 124: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------------------- Limit Output: t1.c1 -> Nested Loop Anti Join Output: t1.c1 Join Filter: (t1.c1 = t2.c2) -> Foreign Scan on public.ft1 t1 Output: t1.c1 SQLite query: SELECT `C 1` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST -> Materialize Output: t2.c2 -> Foreign Scan on public.ft2 t2 Output: t2.c2 SQLite query: SELECT `c2` FROM main."T 1" (13 rows) --Testcase 125: SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10; c1 ----- 110 111 112 113 114 115 116 117 118 119 (10 rows) -- CROSS JOIN can be pushed down --Testcase 126: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1.c1, t2.c1 SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (TRUE)) ORDER BY r1.`C 1` ASC NULLS LAST, r2.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 (3 rows) --Testcase 127: SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; c1 | c1 ----+----- 1 | 101 1 | 102 1 | 103 1 | 104 1 | 105 1 | 106 1 | 107 1 | 108 1 | 109 1 | 110 (10 rows) -- different server, not pushed down. No result expected. --Testcase 128: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; QUERY PLAN -------------------------------------------------------------------------------------------- Limit Output: t1.c1, t2.c1 -> Merge Join Output: t1.c1, t2.c1 Merge Cond: (t1.c1 = t2.c1) -> Foreign Scan on public.ft5 t1 Output: t1.c1, t1.c2, t1.c3 SQLite query: SELECT `c1` FROM main."T 4" ORDER BY `c1` ASC NULLS LAST -> Materialize Output: t2.c1, t2.c2, t2.c3 -> Foreign Scan on public.ft6 t2 Output: t2.c1, t2.c2, t2.c3 SQLite query: SELECT `c1` FROM main."T 4" ORDER BY `c1` ASC NULLS LAST (13 rows) --Testcase 129: SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; c1 | c1 ----+---- (0 rows) -- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS -- JOIN since c8 in both tables has same value. --Testcase 130: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1.c1, t2.c1 SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`c8` = r2.`c8`)))) ORDER BY r1.`C 1` ASC NULLS LAST, r2.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 (3 rows) --Testcase 131: SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10; c1 | c1 ----+----- 1 | 101 1 | 102 1 | 103 1 | 104 1 | 105 1 | 106 1 | 107 1 | 108 1 | 109 1 | 110 (10 rows) -- unsafe conditions on one side (c8 has a UDT), not pushed down. --Testcase 132: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1.c1, t2.c1, t1.c3 SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3` FROM (main."T 1" r1 LEFT JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)))) WHERE ((r1.`c8` = 'foo')) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 (3 rows) --Testcase 133: SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; c1 | c1 -----+----- 101 | 101 102 | 102 103 | 103 104 | 104 105 | 105 106 | 106 107 | 107 108 | 108 109 | 109 110 | 110 (10 rows) -- join where unsafe to pushdown condition in WHERE clause has a column not -- in the SELECT clause. In this test unsafe clause needs to have column -- references from both joining sides so that the clause is not pushed down -- into one of the joining sides. --Testcase 134: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: t1.c1, t2.c1, t1.c3 SQLite query: SELECT r1.`C 1`, r2.`C 1`, r1.`c3` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`c8` = r2.`c8`)))) ORDER BY r1.`c3` ASC NULLS LAST, r1.`C 1` ASC NULLS LAST LIMIT 10 OFFSET 100 (3 rows) --Testcase 135: SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10; c1 | c1 -----+----- 101 | 101 102 | 102 103 | 103 104 | 104 105 | 105 106 | 106 107 | 107 108 | 108 109 | 109 110 | 110 (10 rows) -- Aggregate after UNION, for testing setrefs --Testcase 136: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------------------- Limit Output: t1.c1, (avg((t1.c1 + t2.c1))) -> Sort Output: t1.c1, (avg((t1.c1 + t2.c1))) Sort Key: t1.c1 -> HashAggregate Output: t1.c1, avg((t1.c1 + t2.c1)) Group Key: t1.c1 -> HashAggregate Output: t1.c1, t2.c1 Group Key: t1.c1, t2.c1 -> Append -> Merge Join Output: t1.c1, t2.c1 Merge Cond: (t1.c1 = t2.c1) -> Sort Output: t1.c1 Sort Key: t1.c1 -> Foreign Scan on public.ft1 t1 Output: t1.c1 SQLite query: SELECT `C 1` FROM main."T 1" -> Sort Output: t2.c1 Sort Key: t2.c1 -> Foreign Scan on public.ft2 t2 Output: t2.c1 SQLite query: SELECT `C 1` FROM main."T 1" -> Merge Join Output: t1_1.c1, t2_1.c1 Merge Cond: (t1_1.c1 = t2_1.c1) -> Sort Output: t1_1.c1 Sort Key: t1_1.c1 -> Foreign Scan on public.ft1 t1_1 Output: t1_1.c1 SQLite query: SELECT `C 1` FROM main."T 1" -> Sort Output: t2_1.c1 Sort Key: t2_1.c1 -> Foreign Scan on public.ft2 t2_1 Output: t2_1.c1 SQLite query: SELECT `C 1` FROM main."T 1" (42 rows) --Testcase 137: SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10; t1c1 | avg ------+---------------------- 101 | 202.0000000000000000 102 | 204.0000000000000000 103 | 206.0000000000000000 104 | 208.0000000000000000 105 | 210.0000000000000000 106 | 212.0000000000000000 107 | 214.0000000000000000 108 | 216.0000000000000000 109 | 218.0000000000000000 110 | 220.0000000000000000 (10 rows) -- join with lateral reference --Testcase 138: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Limit Output: t1."C 1" -> Nested Loop Output: t1."C 1" -> Foreign Scan on "S 1"."T 1" t1 Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `C 1` ASC NULLS LAST -> Unique Output: t2.c1, t3.c1 -> Foreign Scan Output: t2.c1, t3.c1 SQLite query: SELECT r1.`C 1`, r2.`C 1` FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`c2` = ?)))) ORDER BY r1.`C 1` ASC NULLS LAST (12 rows) --Testcase 139: SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10; C 1 ----- 1 1 1 1 1 1 1 1 1 1 (10 rows) -- non-Var items in targetlist of the nullable rel of a join preventing -- push-down in some cases -- unable to push {ft1, ft2} --Testcase 140: EXPLAIN (VERBOSE, COSTS OFF) SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15; QUERY PLAN ---------------------------------------------------------------------------------------------- Nested Loop Left Join Output: (13), ft2.c1 Join Filter: (13 = ft2.c1) -> Foreign Scan on public.ft2 Output: ft2.c1 SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` >= 10)) AND ((`C 1` <= 15)) -> Materialize Output: (13) -> Foreign Scan on public.ft1 Output: 13 SQLite query: SELECT NULL FROM main."T 1" WHERE ((`C 1` = 13)) (11 rows) --Testcase 141: SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15; a | c1 ----+---- | 10 | 11 | 12 13 | 13 | 14 | 15 (6 rows) -- ok to push {ft1, ft2} but not {ft1, ft2, ft4} --Testcase 142: EXPLAIN (VERBOSE, COSTS OFF) SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15; QUERY PLAN ------------------------------------------------------------------------------------------------- Hash Right Join Output: ft4.c1, (13), ft1.c1, ft2.c1 Hash Cond: (ft1.c1 = ft4.c1) -> Nested Loop Output: ft1.c1, ft2.c1, 13 -> Foreign Scan on public.ft1 Output: ft1.c1 SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` = 12)) -> Materialize Output: ft2.c1 -> Foreign Scan on public.ft2 Output: ft2.c1 SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` = 12)) -> Hash Output: ft4.c1 -> Foreign Scan on public.ft4 Output: ft4.c1 SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 10)) AND ((`c1` <= 15)) (18 rows) --Testcase 143: SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15; c1 | a | b | c ----+----+----+---- 12 | 13 | 12 | 12 10 | | | 14 | | | (3 rows) -- join with nullable side with some columns with null values --Testcase 144: UPDATE ft5 SET c3 = null where c1 % 9 = 0; --Testcase 145: EXPLAIN (VERBOSE, COSTS OFF) SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: ft5.*, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 SQLite query: SELECT CASE WHEN ( r1.`c1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) THEN ("(" || COALESCE(r1.`c1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '')|| ")") END, r1.`c1`, r1.`c2`, r1.`c3`, r2.`c1`, r2.`c2` FROM (main."T 4" r1 INNER JOIN main."T 3" r2 ON (((r1.`c1` = r2.`c1`)) AND ((r2.`c1` >= 10)) AND ((r2.`c1` <= 30)))) ORDER BY r1.`c1` ASC NULLS LAST (3 rows) --Testcase 146: SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1; ft5 | c1 | c2 | c3 | c1 | c2 ----------------+----+----+--------+----+---- (12,13,AAA012) | 12 | 13 | AAA012 | 12 | 13 (18,19,) | 18 | 19 | | 18 | 19 (24,25,AAA024) | 24 | 25 | AAA024 | 24 | 25 (30,31,AAA030) | 30 | 31 | AAA030 | 30 | 31 (4 rows) -- multi-way join involving multiple merge joins -- (this case used to have EPQ-related planning problems) --Testcase 506: CREATE TABLE local_tbl (c1 int NOT NULL, c2 int NOT NULL, c3 text, CONSTRAINT local_tbl_pkey PRIMARY KEY (c1)); --Testcase 507: INSERT INTO local_tbl SELECT id, id % 10, to_char(id, 'FM0000') FROM generate_series(1, 1000) id; ANALYZE local_tbl; SET enable_nestloop TO false; SET enable_hashjoin TO false; --Testcase 147: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- LockRows Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3, local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.*, ft2.*, ft4.*, ft5.*, local_tbl.ctid -> Merge Join Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3, local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.*, ft2.*, ft4.*, ft5.*, local_tbl.ctid Merge Cond: (local_tbl.c1 = ft1.c2) -> Index Scan using local_tbl_pkey on public.local_tbl Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid -> Sort Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* Sort Key: ft1.c2 -> Foreign Scan Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* SQLite query: SELECT r1.`C 1`, r1.`c2`, r1.`c3`, r1.`c4`, r1.`c5`, r1.`c6`, r1.`c7`, r1.`c8`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, r2.`C 1`, r2.`c2`, r2.`c3`, r2.`c4`, r2.`c5`, r2.`c6`, r2.`c7`, r2.`c8`, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END, r3.`c1`, r3.`c2`, r3.`c3`, CASE WHEN ( r3.`c1` IS NOT NULL) OR ( r3.`c2` IS NOT NULL) OR ( r3.`c3` IS NOT NULL) THEN ("(" || COALESCE(r3.`c1`, '') || "," || COALESCE(r3.`c2`, '') || "," || COALESCE(r3.`c3`, '')|| ")") END, r4.`c1`, r4.`c2`, r4.`c3`, CASE WHEN ( r4.`c1` IS NOT NULL) OR ( r4.`c2` IS NOT NULL) OR ( r4.`c3` IS NOT NULL) THEN ("(" || COALESCE(r4.`c1`, '') || "," || COALESCE(r4.`c2`, '') || "," || COALESCE(r4.`c3`, '')|| ")") END FROM (((main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r2.`C 1` < 100)) AND ((r1.`C 1` < 100)))) INNER JOIN main."T 3" r3 ON (((r1.`c2` = r3.`c1`)))) INNER JOIN main."T 4" r4 ON (((r1.`c2` = r4.`c1`)))) -> Merge Join Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.*, ft5.c1, ft5.c2, ft5.c3, ft5.* Merge Cond: (ft1.c2 = ft5.c1) -> Sort Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.* Sort Key: ft1.c2 -> Merge Join Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*, ft4.c1, ft4.c2, ft4.c3, ft4.* Merge Cond: (ft1.c2 = ft4.c1) -> Sort Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* Sort Key: ft1.c2 -> Merge Join Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* Merge Cond: (ft1.c1 = ft2.c1) -> Sort Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.* Sort Key: ft1.c1 -> Foreign Scan on public.ft1 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 100)) -> Sort Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* Sort Key: ft2.c1 -> Foreign Scan on public.ft2 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 100)) -> Sort Output: ft4.c1, ft4.c2, ft4.c3, ft4.* Sort Key: ft4.c1 -> Foreign Scan on public.ft4 Output: ft4.c1, ft4.c2, ft4.c3, ft4.* SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" -> Sort Output: ft5.c1, ft5.c2, ft5.c3, ft5.* Sort Key: ft5.c1 -> Foreign Scan on public.ft5 Output: ft5.c1, ft5.c2, ft5.c3, ft5.* SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" (52 rows) --Testcase 148: SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1 AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 ORDER BY ft1.c1 FOR UPDATE; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c1 | c2 | c3 | c1 | c2 | c3 ----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------+----+----+--------+----+----+------ 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006 | 6 | 7 | AAA006 | 6 | 6 | 0006 (10 rows) RESET enable_nestloop; RESET enable_hashjoin; --DROP TABLE local_tbl; -- check join pushdown in situations where multiple userids are involved --Testcase 508: CREATE ROLE regress_view_owner SUPERUSER; --Testcase 509: CREATE USER MAPPING FOR regress_view_owner SERVER sqlite_svr; GRANT SELECT ON ft4 TO regress_view_owner; GRANT SELECT ON ft5 TO regress_view_owner; --Testcase 510: CREATE VIEW v4 AS SELECT * FROM ft4; --Testcase 511: CREATE VIEW v5 AS SELECT * FROM ft5; ALTER VIEW v5 OWNER TO regress_view_owner; --Testcase 149: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can't be pushed down, different view owners QUERY PLAN --------------------------------------------------------------------------- Limit Output: ft4.c1, ft5.c2, ft5.c1 -> Incremental Sort Output: ft4.c1, ft5.c2, ft5.c1 Sort Key: ft4.c1, ft5.c1 Presorted Key: ft4.c1 -> Merge Left Join Output: ft4.c1, ft5.c2, ft5.c1 Merge Cond: (ft4.c1 = ft5.c1) -> Sort Output: ft4.c1 Sort Key: ft4.c1 -> Foreign Scan on public.ft4 Output: ft4.c1 SQLite query: SELECT `c1` FROM main."T 3" -> Sort Output: ft5.c2, ft5.c1 Sort Key: ft5.c1 -> Foreign Scan on public.ft5 Output: ft5.c2, ft5.c1 SQLite query: SELECT `c1`, `c2` FROM main."T 4" (21 rows) --Testcase 150: SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; c1 | c2 ----+---- 22 | 24 | 25 26 | 28 | 30 | 31 32 | 34 | 36 | 37 38 | 40 | (10 rows) ALTER VIEW v4 OWNER TO regress_view_owner; --Testcase 151: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can be pushed down QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: ft4.c1, ft5.c2, ft5.c1 SQLite query: SELECT r6.`c1`, r9.`c2`, r9.`c1` FROM (main."T 3" r6 LEFT JOIN main."T 4" r9 ON (((r6.`c1` = r9.`c1`)))) ORDER BY r6.`c1` ASC NULLS LAST, r9.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 (3 rows) --Testcase 152: SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; c1 | c2 ----+---- 22 | 24 | 25 26 | 28 | 30 | 31 32 | 34 | 36 | 37 38 | 40 | (10 rows) --Testcase 153: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can't be pushed down, view owner not current user QUERY PLAN --------------------------------------------------------------------------- Limit Output: ft4.c1, t2.c2, t2.c1 -> Incremental Sort Output: ft4.c1, t2.c2, t2.c1 Sort Key: ft4.c1, t2.c1 Presorted Key: ft4.c1 -> Merge Left Join Output: ft4.c1, t2.c2, t2.c1 Merge Cond: (ft4.c1 = t2.c1) -> Sort Output: ft4.c1 Sort Key: ft4.c1 -> Foreign Scan on public.ft4 Output: ft4.c1 SQLite query: SELECT `c1` FROM main."T 3" -> Sort Output: t2.c2, t2.c1 Sort Key: t2.c1 -> Foreign Scan on public.ft5 t2 Output: t2.c2, t2.c1 SQLite query: SELECT `c1`, `c2` FROM main."T 4" (21 rows) --Testcase 154: SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; c1 | c2 ----+---- 22 | 24 | 25 26 | 28 | 30 | 31 32 | 34 | 36 | 37 38 | 40 | (10 rows) ALTER VIEW v4 OWNER TO CURRENT_USER; --Testcase 155: EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; -- can be pushed down QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: ft4.c1, t2.c2, t2.c1 SQLite query: SELECT r6.`c1`, r2.`c2`, r2.`c1` FROM (main."T 3" r6 LEFT JOIN main."T 4" r2 ON (((r6.`c1` = r2.`c1`)))) ORDER BY r6.`c1` ASC NULLS LAST, r2.`c1` ASC NULLS LAST LIMIT 10 OFFSET 10 (3 rows) --Testcase 156: SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10; c1 | c2 ----+---- 22 | 24 | 25 26 | 28 | 30 | 31 32 | 34 | 36 | 37 38 | 40 | (10 rows) ALTER VIEW v4 OWNER TO regress_view_owner; -- cleanup --Testcase 512: DROP OWNED BY regress_view_owner; --Testcase 513: DROP ROLE regress_view_owner; -- =================================================================== -- Aggregate and grouping queries -- =================================================================== -- Simple aggregates --Testcase 157: explain (verbose, costs off) select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------- Result Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2 -> Sort Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2 Sort Key: (count(ft1.c6)), (sum(ft1.c1)) -> GroupAggregate Output: count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), c2 Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c6, c1, c2 SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 5)) ORDER BY `c2` ASC NULLS LAST (11 rows) --Testcase 158: select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2; count | sum | avg | min | max | stddev | sum2 -------+-------+----------------------+-----+------+--------+------- 100 | 49600 | 496.0000000000000000 | 1 | 991 | 0 | 49600 100 | 49700 | 497.0000000000000000 | 2 | 992 | 0 | 49700 100 | 49800 | 498.0000000000000000 | 3 | 993 | 0 | 49800 100 | 49900 | 499.0000000000000000 | 4 | 994 | 0 | 49900 100 | 50500 | 505.0000000000000000 | 0 | 1000 | 0 | 50500 (5 rows) --Testcase 514: explain (verbose, costs off) select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2 limit 1; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------- Limit Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), (((sum(c1)) * ((random() <= '1'::double precision))::integer)), c2 -> Result Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2 -> Sort Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2 Sort Key: (count(ft1.c6)), (sum(ft1.c1)) -> GroupAggregate Output: count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), c2 Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c6, c1, c2 SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 5)) ORDER BY `c2` ASC NULLS LAST (13 rows) --Testcase 515: select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2 limit 1; count | sum | avg | min | max | stddev | sum2 -------+-------+----------------------+-----+-----+--------+------- 100 | 49600 | 496.0000000000000000 | 1 | 991 | 0 | 49600 (1 row) -- Aggregate is not pushed down as aggregation contains random() --Testcase 159: explain (verbose, costs off) select sum(c1 * (random() <= 1)::int) as sum, avg(c1) from ft1; QUERY PLAN ------------------------------------------------------------------------------- Aggregate Output: sum((c1 * ((random() <= '1'::double precision))::integer)), avg(c1) -> Foreign Scan on public.ft1 Output: c1 SQLite query: SELECT `C 1` FROM main."T 1" (5 rows) -- Aggregate over join query --Testcase 160: explain (verbose, costs off) select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------ Foreign Scan Output: (count(*)), (sum(t1.c1)), (avg(t2.c1)) SQLite query: SELECT count(*), sum(r1.`C 1`), avg(r2.`C 1`) FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r2.`c2` = 6)) AND ((r1.`c2` = 6)))) (3 rows) --Testcase 161: select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6; count | sum | avg -------+---------+----- 10000 | 5010000 | 501 (1 row) -- Not pushed down due to local conditions present in underneath input rel --Testcase 162: explain (verbose, costs off) select sum(t1.c1), count(t2.c1) from ft1 t1 inner join ft2 t2 on (t1.c1 = t2.c1) where ((t1.c1 * t2.c1)/(t1.c1 * t2.c1)) * random() <= 1; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Aggregate Output: sum(t1.c1), count(t2.c1) -> Merge Join Output: t1.c1, t2.c1 Merge Cond: (t1.c1 = t2.c1) Join Filter: (((((t1.c1 * t2.c1) / (t1.c1 * t2.c1)))::double precision * random()) <= '1'::double precision) -> Sort Output: t1.c1 Sort Key: t1.c1 -> Foreign Scan on public.ft1 t1 Output: t1.c1 SQLite query: SELECT `C 1` FROM main."T 1" -> Sort Output: t2.c1 Sort Key: t2.c1 -> Foreign Scan on public.ft2 t2 Output: t2.c1 SQLite query: SELECT `C 1` FROM main."T 1" (18 rows) -- GROUP BY clause having expressions --Testcase 163: explain (verbose, costs off) select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: ((c2 / 2)), ((sum(c2) * (c2 / 2))) SQLite query: SELECT (`c2` / 2), (sum(`c2`) * (`c2` / 2)) FROM main."T 1" GROUP BY 1 ORDER BY (`c2` / 2) ASC NULLS LAST (3 rows) --Testcase 164: select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2; ?column? | ?column? ----------+---------- 0 | 0 1 | 500 2 | 1800 3 | 3900 4 | 6800 (5 rows) -- Aggregates in subquery are pushed down. --Testcase 165: explain (verbose, costs off) select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x; QUERY PLAN ------------------------------------------------------------------------------- Aggregate Output: count(ft1.c2), sum(ft1.c2) -> Sort Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision)) Sort Key: ft1.c2, (sum(ft1.c1)) -> HashAggregate Output: ft1.c2, sum(ft1.c1), (sqrt((ft1.c1)::double precision)) Group Key: ft1.c2, sqrt((ft1.c1)::double precision) -> Foreign Scan on public.ft1 Output: ft1.c2, sqrt((ft1.c1)::double precision), ft1.c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" (11 rows) --Testcase 166: select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x; count | sum -------+------ 1000 | 4500 (1 row) -- Aggregate is still pushed down by taking unshippable expression out --Testcase 167: explain (verbose, costs off) select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2; QUERY PLAN --------------------------------------------------------------------------------------------------- Sort Output: ((c2 * ((random() <= '1'::double precision))::integer)), ((sum(c1) * c2)), c2 Sort Key: ((ft1.c2 * ((random() <= '1'::double precision))::integer)), ((sum(ft1.c1) * ft1.c2)) -> Foreign Scan Output: (c2 * ((random() <= '1'::double precision))::integer), ((sum(c1) * c2)), c2 SQLite query: SELECT (sum(`C 1`) * `c2`), `c2` FROM main."T 1" GROUP BY 2 (6 rows) --Testcase 168: select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2; sum1 | sum2 ------+-------- 0 | 0 1 | 49600 2 | 99400 3 | 149400 4 | 199600 5 | 250000 6 | 300600 7 | 351400 8 | 402400 9 | 453600 (10 rows) -- Aggregate with unshippable GROUP BY clause are not pushed --Testcase 169: explain (verbose, costs off) select c2 * (random() <= 1)::int as c2 from ft2 group by c2 * (random() <= 1)::int order by 1; QUERY PLAN ------------------------------------------------------------------------------ Sort Output: ((c2 * ((random() <= '1'::double precision))::integer)) Sort Key: ((ft2.c2 * ((random() <= '1'::double precision))::integer)) -> HashAggregate Output: ((c2 * ((random() <= '1'::double precision))::integer)) Group Key: (ft2.c2 * ((random() <= '1'::double precision))::integer) -> Foreign Scan on public.ft2 Output: (c2 * ((random() <= '1'::double precision))::integer) SQLite query: SELECT `c2` FROM main."T 1" (9 rows) -- GROUP BY clause in various forms, cardinal, alias and constant expression --Testcase 516: explain (verbose, costs off) select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2; QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: (count(c2)), c2, 5, 7.0, 9 SQLite query: SELECT count(`c2`), `c2`, 5, 7.0, 9 FROM main."T 1" GROUP BY 2, 3, 5 ORDER BY `c2` ASC NULLS LAST (3 rows) --Testcase 517: select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2; w | x | y | z -----+---+---+----- 100 | 0 | 5 | 7.0 100 | 1 | 5 | 7.0 100 | 2 | 5 | 7.0 100 | 3 | 5 | 7.0 100 | 4 | 5 | 7.0 100 | 5 | 5 | 7.0 100 | 6 | 5 | 7.0 100 | 7 | 5 | 7.0 100 | 8 | 5 | 7.0 100 | 9 | 5 | 7.0 (10 rows) -- GROUP BY clause referring to same column multiple times -- Also, ORDER BY contains an aggregate function --Testcase 170: explain (verbose, costs off) select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1); QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: c2, c2, (sum(c1)) SQLite query: SELECT `c2`, `c2`, sum(`C 1`) FROM main."T 1" WHERE ((`c2` > 6)) GROUP BY 1, 2 ORDER BY sum(`C 1`) ASC NULLS LAST (3 rows) --Testcase 171: select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1); c2 | c2 ----+---- 7 | 7 8 | 8 9 | 9 (3 rows) -- Testing HAVING clause shippability --Testcase 172: explain (verbose, costs off) select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan Output: c2, (sum(c1)) SQLite query: SELECT `c2`, sum(`C 1`) FROM main."T 1" GROUP BY 1 HAVING ((avg(`C 1`) < 500)) AND ((sum(`C 1`) < 49800)) ORDER BY `c2` ASC NULLS LAST (3 rows) --Testcase 173: select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2; c2 | sum ----+------- 1 | 49600 2 | 49700 (2 rows) -- Unshippable HAVING clause will be evaluated locally, and other qual in HAVING clause is pushed down --Testcase 174: explain (verbose, costs off) select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------- Aggregate Output: count(*) -> HashAggregate Output: ft1.c5, NULL::bigint, (sqrt((ft1.c2)::double precision)) Group Key: ft1.c5, sqrt((ft1.c2)::double precision) Filter: ((avg(ft1.c1) < '500'::numeric) AND ((((avg(ft1.c1) / avg(ft1.c1)))::double precision * random()) <= '1'::double precision)) -> Foreign Scan on public.ft1 Output: ft1.c5, sqrt((ft1.c2)::double precision), ft1.c1 SQLite query: SELECT `C 1`, `c2`, `c5` FROM main."T 1" (9 rows) --Testcase 175: select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x; count ------- 49 (1 row) -- Aggregate in HAVING clause is not pushable, and thus aggregation is not pushed down --Testcase 176: explain (verbose, costs off) select sum(c1) from ft1 group by c2 having avg(c1 * (random() <= 1)::int) > 100 order by 1; QUERY PLAN --------------------------------------------------------------------------------------------------- Sort Output: (sum(c1)), c2 Sort Key: (sum(ft1.c1)) -> GroupAggregate Output: sum(c1), c2 Group Key: ft1.c2 Filter: (avg((ft1.c1 * ((random() <= '1'::double precision))::integer)) > '100'::numeric) -> Foreign Scan on public.ft1 Output: c1, c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST (10 rows) -- Remote aggregate in combination with a local Param (for the output -- of an initplan) can be trouble, per bug #15781 --Testcase 518: explain (verbose, costs off) select exists(select 1 from pg_enum), sum(c1) from ft1; QUERY PLAN --------------------------------------------------- Foreign Scan Output: $0, (sum(ft1.c1)) SQLite query: SELECT sum(`C 1`) FROM main."T 1" InitPlan 1 (returns $0) -> Seq Scan on pg_catalog.pg_enum (5 rows) --Testcase 519: select exists(select 1 from pg_enum), sum(c1) from ft1; exists | sum --------+-------- f | 500500 (1 row) --Testcase 520: explain (verbose, costs off) select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1; QUERY PLAN ---------------------------------------------------- GroupAggregate Output: ($0), sum(ft1.c1) Group Key: $0 InitPlan 1 (returns $0) -> Seq Scan on pg_catalog.pg_enum -> Foreign Scan on public.ft1 Output: $0, ft1.c1 SQLite query: SELECT `C 1` FROM main."T 1" (8 rows) --Testcase 521: select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1; exists | sum --------+-------- f | 500500 (1 row) -- Testing ORDER BY, DISTINCT, FILTER, Ordered-sets and VARIADIC within aggregates -- ORDER BY within aggregate, same column used to order --Testcase 177: explain (verbose, costs off) select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1; QUERY PLAN ------------------------------------------------------------------------------------------------------------------- Sort Output: (array_agg(c1 ORDER BY c1)), c2 Sort Key: (array_agg(ft1.c1 ORDER BY ft1.c1)) -> GroupAggregate Output: array_agg(c1 ORDER BY c1), c2 Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c1, c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) ORDER BY `c2` ASC NULLS LAST (9 rows) --Testcase 178: select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1; array_agg -------------------------------- {1,11,21,31,41,51,61,71,81,91} {2,12,22,32,42,52,62,72,82,92} {3,13,23,33,43,53,63,73,83,93} {4,14,24,34,44,54,64,74,84,94} {5,15,25,35,45,55,65,75,85,95} {6,16,26,36,46,56,66,76,86,96} {7,17,27,37,47,57,67,77,87,97} {8,18,28,38,48,58,68,78,88,98} {9,19,29,39,49,59,69,79,89,99} {10,20,30,40,50,60,70,80,90} (10 rows) -- ORDER BY within aggregate, different column used to order also using DESC --Testcase 179: explain (verbose, costs off) select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50; QUERY PLAN ------------------------------------------------------------------------------------------------ Aggregate Output: array_agg(c5 ORDER BY c1 DESC) -> Foreign Scan on public.ft2 Output: c5, c1 SQLite query: SELECT `C 1`, `c5` FROM main."T 1" WHERE ((`C 1` < 50)) AND ((`c2` = 6)) (5 rows) --Testcase 180: select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50; array_agg ------------------------------------------------------------------------------------------------------------------------------------------ {"Mon Feb 16 00:00:00 1970","Fri Feb 06 00:00:00 1970","Tue Jan 27 00:00:00 1970","Sat Jan 17 00:00:00 1970","Wed Jan 07 00:00:00 1970"} (1 row) -- DISTINCT within aggregate --Testcase 181: explain (verbose, costs off) select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; QUERY PLAN -------------------------------------------------------------------------------------------------------------- Sort Output: (array_agg(DISTINCT (t1.c1 % 5))), ((t2.c1 % 3)) Sort Key: (array_agg(DISTINCT (t1.c1 % 5))) -> GroupAggregate Output: array_agg(DISTINCT (t1.c1 % 5)), ((t2.c1 % 3)) Group Key: ((t2.c1 % 3)) -> Sort Output: ((t2.c1 % 3)), t1.c1 Sort Key: ((t2.c1 % 3)) -> Hash Full Join Output: (t2.c1 % 3), t1.c1 Hash Cond: (t1.c1 = t2.c1) Filter: ((t1.c1 < 20) OR ((t1.c1 IS NULL) AND (t2.c1 < 5))) -> Foreign Scan on public.ft4 t1 Output: t1.c1, t1.c2, t1.c3 SQLite query: SELECT `c1` FROM main."T 3" -> Hash Output: t2.c1 -> Foreign Scan on public.ft5 t2 Output: t2.c1 SQLite query: SELECT `c1` FROM main."T 4" ORDER BY (`c1` % 3) ASC NULLS LAST (21 rows) --Testcase 182: select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; array_agg -------------- {0,1,2,3,4} {1,2,3,NULL} (2 rows) -- DISTINCT combined with ORDER BY within aggregate --Testcase 183: explain (verbose, costs off) select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; QUERY PLAN -------------------------------------------------------------------------------------------------------------- Sort Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))), ((t2.c1 % 3)) Sort Key: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))) -> GroupAggregate Output: array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5)), ((t2.c1 % 3)) Group Key: ((t2.c1 % 3)) -> Sort Output: ((t2.c1 % 3)), t1.c1 Sort Key: ((t2.c1 % 3)) -> Hash Full Join Output: (t2.c1 % 3), t1.c1 Hash Cond: (t1.c1 = t2.c1) Filter: ((t1.c1 < 20) OR ((t1.c1 IS NULL) AND (t2.c1 < 5))) -> Foreign Scan on public.ft4 t1 Output: t1.c1, t1.c2, t1.c3 SQLite query: SELECT `c1` FROM main."T 3" -> Hash Output: t2.c1 -> Foreign Scan on public.ft5 t2 Output: t2.c1 SQLite query: SELECT `c1` FROM main."T 4" ORDER BY (`c1` % 3) ASC NULLS LAST (21 rows) --Testcase 184: select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; array_agg -------------- {0,1,2,3,4} {1,2,3,NULL} (2 rows) --Testcase 185: explain (verbose, costs off) select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; QUERY PLAN -------------------------------------------------------------------------------------------------------------- Sort Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)), ((t2.c1 % 3)) Sort Key: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)) -> GroupAggregate Output: array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST), ((t2.c1 % 3)) Group Key: ((t2.c1 % 3)) -> Sort Output: ((t2.c1 % 3)), t1.c1 Sort Key: ((t2.c1 % 3)) -> Hash Full Join Output: (t2.c1 % 3), t1.c1 Hash Cond: (t1.c1 = t2.c1) Filter: ((t1.c1 < 20) OR ((t1.c1 IS NULL) AND (t2.c1 < 5))) -> Foreign Scan on public.ft4 t1 Output: t1.c1, t1.c2, t1.c3 SQLite query: SELECT `c1` FROM main."T 3" -> Hash Output: t2.c1 -> Foreign Scan on public.ft5 t2 Output: t2.c1 SQLite query: SELECT `c1` FROM main."T 4" ORDER BY (`c1` % 3) ASC NULLS LAST (21 rows) --Testcase 186: select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1; array_agg -------------- {3,2,1,NULL} {4,3,2,1,0} (2 rows) -- FILTER within aggregate --Testcase 187: explain (verbose, costs off) select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last; QUERY PLAN --------------------------------------------------------------------------------------------- Sort Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2 Sort Key: (sum(ft1.c1) FILTER (WHERE ((ft1.c1 < 100) AND (ft1.c2 > 5)))) -> GroupAggregate Output: sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5))), c2 Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c1, c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST (9 rows) --Testcase 188: select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last; sum ----- 510 520 530 540 (10 rows) -- DISTINCT, ORDER BY and FILTER within aggregate --Testcase 189: explain (verbose, costs off) select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2; QUERY PLAN ----------------------------------------------------------------------------------------------------- GroupAggregate Output: sum((c1 % 3)), sum(DISTINCT (c1 % 3) ORDER BY (c1 % 3)) FILTER (WHERE ((c1 % 3) < 2)), c2 Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c1, c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` = 6)) (6 rows) --Testcase 190: select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2; sum | sum | c2 -----+-----+---- 99 | 1 | 6 (1 row) -- Outer query is aggregation query --Testcase 191: explain (verbose, costs off) select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; QUERY PLAN ----------------------------------------------------------------------------------------------- Unique Output: ((SubPlan 1)) -> Sort Output: ((SubPlan 1)) Sort Key: ((SubPlan 1)) -> Aggregate Output: (SubPlan 1) -> Foreign Scan on public.ft2 t2 Output: t2.c2, t2.c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE (((`c2` % 6) = 0)) SubPlan 1 -> Foreign Scan on public.ft1 t1 Output: count(*) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))) SQLite query: SELECT NULL FROM main."T 1" WHERE ((`C 1` = 6)) (14 rows) --Testcase 192: select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; count ------- 1 (1 row) -- Inner query is aggregation query --Testcase 193: explain (verbose, costs off) select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; QUERY PLAN -------------------------------------------------------------------------------------------- Unique Output: ((SubPlan 1)) -> Sort Output: ((SubPlan 1)) Sort Key: ((SubPlan 1)) -> Foreign Scan on public.ft2 t2 Output: (SubPlan 1) SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE (((`c2` % 6) = 0)) SubPlan 1 -> Aggregate Output: count(t1.c1) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))) -> Foreign Scan on public.ft1 t1 Output: t1.c1 SQLite query: SELECT `C 1` FROM main."T 1" WHERE ((`C 1` = 6)) (14 rows) --Testcase 194: select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1; count ------- 0 1 (2 rows) -- Aggregate not pushed down as FILTER condition is not pushable --Testcase 195: explain (verbose, costs off) select sum(c1) filter (where (c1 / c1) * random() <= 1) from ft1 group by c2 order by 1; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------ Sort Output: (sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision))), c2 Sort Key: (sum(ft1.c1) FILTER (WHERE ((((ft1.c1 / ft1.c1))::double precision * random()) <= '1'::double precision))) -> GroupAggregate Output: sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision)), c2 Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c1, c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST (9 rows) --Testcase 196: explain (verbose, costs off) select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1; QUERY PLAN ------------------------------------------------------------------------ Aggregate Output: sum(ft1.c2) FILTER (WHERE (hashed SubPlan 1)) -> Foreign Scan on public.ft1 Output: ft1.c2 SQLite query: SELECT `c2` FROM main."T 1" SubPlan 1 -> Foreign Scan on public.ft1 ft1_1 Output: ft1_1.c2 SQLite query: SELECT `c2` FROM main."T 1" WHERE ((`c2` < 5)) (9 rows) -- Ordered-sets within aggregate --Testcase 197: explain (verbose, costs off) select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2; QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- GroupAggregate Output: c2, rank('10'::character varying) WITHIN GROUP (ORDER BY c6), percentile_cont((((c2)::numeric / '10'::numeric))::double precision) WITHIN GROUP (ORDER BY ((c1)::double precision)) Group Key: ft1.c2 Filter: (percentile_cont((((ft1.c2)::numeric / '10'::numeric))::double precision) WITHIN GROUP (ORDER BY ((ft1.c1)::double precision)) < '500'::double precision) -> Foreign Scan on public.ft1 Output: c2, c6, c1 SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 10)) ORDER BY `c2` ASC NULLS LAST (7 rows) --Testcase 198: select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2; c2 | rank | percentile_cont ----+------+----------------- 0 | 101 | 10 1 | 101 | 100 2 | 1 | 200 3 | 1 | 300 4 | 1 | 400 (5 rows) -- Using multiple arguments within aggregates --Testcase 199: explain (verbose, costs off) select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1; QUERY PLAN ----------------------------------------------------------------------------------------------------------- GroupAggregate Output: c1, rank(c1, c2) WITHIN GROUP (ORDER BY c1, c2), c2 Group Key: ft1.c1, ft1.c2 -> Foreign Scan on public.ft1 Output: c1, c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` = 6)) ORDER BY `c2` ASC NULLS LAST (6 rows) --Testcase 200: select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1; c1 | rank ----+------ 6 | 1 (1 row) -- User defined function for user defined aggregate, VARIADIC --Testcase 522: create function least_accum(anyelement, variadic anyarray) returns anyelement language sql as 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)'; --Testcase 523: create aggregate least_agg(variadic items anyarray) ( stype = anyelement, sfunc = least_accum ); -- Disable hash aggregation for plan stability. set enable_hashagg to false; -- Not pushed down due to user defined aggregate --Testcase 524: explain (verbose, costs off) select c2, least_agg(c1) from ft1 group by c2 order by c2; QUERY PLAN --------------------------------------------------------------------------------------- GroupAggregate Output: c2, least_agg(VARIADIC ARRAY[c1]) Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c2, c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST (6 rows) -- Add function and aggregate into extension --alter extension postgres_fdw add function least_accum(anyelement, variadic anyarray); --alter extension postgres_fdw add aggregate least_agg(variadic items anyarray); --alter server loopback options (set extensions 'postgres_fdw'); -- Now aggregate will be pushed. Aggregate will display VARIADIC argument. --Testcase 525: explain (verbose, costs off) select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2; QUERY PLAN ------------------------------------------------------------------------------------------------------------ GroupAggregate Output: c2, least_agg(VARIADIC ARRAY[c1]) Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c2, c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 100)) ORDER BY `c2` ASC NULLS LAST (6 rows) --Testcase 526: select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2; c2 | least_agg ----+----------- 0 | 10 1 | 1 2 | 2 3 | 3 4 | 4 5 | 5 6 | 6 7 | 7 8 | 8 9 | 9 (10 rows) -- Remove function and aggregate from extension --alter extension postgres_fdw drop function least_accum(anyelement, variadic anyarray); --alter extension postgres_fdw drop aggregate least_agg(variadic items anyarray); --alter server loopback options (set extensions 'postgres_fdw'); -- Not pushed down as we have dropped objects from extension. --Testcase 527: explain (verbose, costs off) select c2, least_agg(c1) from ft1 group by c2 order by c2; QUERY PLAN --------------------------------------------------------------------------------------- GroupAggregate Output: c2, least_agg(VARIADIC ARRAY[c1]) Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c2, c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" ORDER BY `c2` ASC NULLS LAST (6 rows) -- Cleanup reset enable_hashagg; --Testcase 528: drop aggregate least_agg(variadic items anyarray); --Testcase 529: drop function least_accum(anyelement, variadic anyarray); -- Testing USING OPERATOR() in ORDER BY within aggregate. -- For this, we need user defined operators along with operator family and -- operator class. Create those and then add them in extension. Note that -- user defined objects are considered unshippable unless they are part of -- the extension. --Testcase 530: create operator public.<^ ( leftarg = int4, rightarg = int4, procedure = int4eq ); --Testcase 531: create operator public.=^ ( leftarg = int4, rightarg = int4, procedure = int4lt ); --Testcase 532: create operator public.>^ ( leftarg = int4, rightarg = int4, procedure = int4gt ); --Testcase 533: create operator family my_op_family using btree; --Testcase 534: create function my_op_cmp(a int, b int) returns int as $$begin return btint4cmp(a, b); end $$ language plpgsql; --Testcase 535: create operator class my_op_class for type int using btree family my_op_family as operator 1 public.<^, operator 3 public.=^, operator 5 public.>^, function 1 my_op_cmp(int, int); -- This will not be pushed as user defined sort operator is not part of the -- extension yet. --Testcase 536: explain (verbose, costs off) select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; QUERY PLAN ------------------------------------------------------------------------------------------------- GroupAggregate Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2 Group Key: ft2.c2 -> Foreign Scan on public.ft2 Output: c1, c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) AND ((`c2` = 6)) (6 rows) -- Update local stats on ft2 --ANALYZE ft2; -- Add into extension alter extension sqlite_fdw add operator class my_op_class using btree; alter extension sqlite_fdw add function my_op_cmp(a int, b int); alter extension sqlite_fdw add operator family my_op_family using btree; alter extension sqlite_fdw add operator public.<^(int, int); alter extension sqlite_fdw add operator public.=^(int, int); alter extension sqlite_fdw add operator public.>^(int, int); --alter server loopback options (set extensions 'postgres_fdw'); -- Now this will be pushed as sort operator is part of the extension. --Testcase 537: explain (verbose, costs off) select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; QUERY PLAN ------------------------------------------------------------------------------------------------- GroupAggregate Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2 Group Key: ft2.c2 -> Foreign Scan on public.ft2 Output: c1, c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) AND ((`c2` = 6)) (6 rows) --Testcase 538: select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; array_agg -------------------------------- {6,16,26,36,46,56,66,76,86,96} (1 row) -- Remove from extension alter extension sqlite_fdw drop operator class my_op_class using btree; alter extension sqlite_fdw drop function my_op_cmp(a int, b int); alter extension sqlite_fdw drop operator family my_op_family using btree; alter extension sqlite_fdw drop operator public.<^(int, int); alter extension sqlite_fdw drop operator public.=^(int, int); alter extension sqlite_fdw drop operator public.>^(int, int); --alter server loopback options (set extensions 'postgres_fdw'); -- This will not be pushed as sort operator is now removed from the extension. --Testcase 539: explain (verbose, costs off) select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2; QUERY PLAN ------------------------------------------------------------------------------------------------- GroupAggregate Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2 Group Key: ft2.c2 -> Foreign Scan on public.ft2 Output: c1, c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 100)) AND ((`c2` = 6)) (6 rows) -- Cleanup --Testcase 540: drop operator class my_op_class using btree; --Testcase 541: drop function my_op_cmp(a int, b int); --Testcase 542: drop operator family my_op_family using btree; --Testcase 543: drop operator public.>^(int, int); --Testcase 544: drop operator public.=^(int, int); --Testcase 545: drop operator public.<^(int, int); -- Input relation to aggregate push down hook is not safe to pushdown and thus -- the aggregate cannot be pushed down to foreign server. --Testcase 201: explain (verbose, costs off) select count(t1.c3) from ft2 t1 left join ft2 t2 on (t1.c1 = random() * t2.c2); QUERY PLAN ------------------------------------------------------------------------------------------- Aggregate Output: count(t1.c3) -> Nested Loop Left Join Output: t1.c3 Join Filter: ((t1.c1)::double precision = (random() * (t2.c2)::double precision)) -> Foreign Scan on public.ft2 t1 Output: t1.c3, t1.c1 SQLite query: SELECT `C 1`, `c3` FROM main."T 1" -> Materialize Output: t2.c2 -> Foreign Scan on public.ft2 t2 Output: t2.c2 SQLite query: SELECT `c2` FROM main."T 1" (13 rows) -- Subquery in FROM clause having aggregate --Testcase 202: explain (verbose, costs off) select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2; QUERY PLAN -------------------------------------------------------------------------------------------------------- Sort Output: (count(*)), x.b Sort Key: (count(*)), x.b -> GroupAggregate Output: count(*), x.b Group Key: x.b -> Sort Output: x.b Sort Key: x.b -> Hash Join Output: x.b Inner Unique: true Hash Cond: (ft1.c2 = x.a) -> Foreign Scan on public.ft1 Output: ft1.c2 SQLite query: SELECT `c2` FROM main."T 1" -> Hash Output: x.b, x.a -> Subquery Scan on x Output: x.b, x.a -> Foreign Scan Output: ft1_1.c2, (sum(ft1_1.c1)) SQLite query: SELECT `c2`, sum(`C 1`) FROM main."T 1" GROUP BY 1 (23 rows) --Testcase 203: select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2; count | b -------+------- 100 | 49600 100 | 49700 100 | 49800 100 | 49900 100 | 50000 100 | 50100 100 | 50200 100 | 50300 100 | 50400 100 | 50500 (10 rows) -- FULL join with IS NULL check in HAVING --Testcase 204: explain (verbose, costs off) select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2; QUERY PLAN -------------------------------------------------------------------------------------------------- Sort Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1 Sort Key: (avg(t1.c1)), (sum(t2.c1)) -> HashAggregate Output: avg(t1.c1), sum(t2.c1), t2.c1 Group Key: t2.c1 Filter: (((avg(t1.c1) IS NULL) AND (sum(t2.c1) < 10)) OR (sum(t2.c1) IS NULL)) -> Hash Full Join Output: t2.c1, t1.c1 Hash Cond: (t1.c1 = t2.c1) -> Foreign Scan on public.ft4 t1 Output: t1.c1, t1.c2, t1.c3 SQLite query: SELECT `c1` FROM main."T 3" -> Hash Output: t2.c1 -> Foreign Scan on public.ft5 t2 Output: t2.c1 SQLite query: SELECT `c1` FROM main."T 4" ORDER BY `c1` ASC NULLS LAST (18 rows) --Testcase 205: select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2; avg | sum ---------------------+----- 51.0000000000000000 | | 3 | 9 (3 rows) -- Aggregate over FULL join needing to deparse the joining relations as -- subqueries. --Testcase 206: explain (verbose, costs off) select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1); QUERY PLAN ------------------------------------------------------------------------------------------------------- Aggregate Output: count(*), sum(ft4.c1), avg(ft5.c1) -> Hash Full Join Output: ft4.c1, ft5.c1 Hash Cond: (ft4.c1 = ft5.c1) -> Foreign Scan on public.ft4 Output: ft4.c1, ft4.c2, ft4.c3 SQLite query: SELECT `c1` FROM main."T 3" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) -> Hash Output: ft5.c1 -> Foreign Scan on public.ft5 Output: ft5.c1 SQLite query: SELECT `c1` FROM main."T 4" WHERE ((`c1` >= 50)) AND ((`c1` <= 60)) (13 rows) --Testcase 207: select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1); count | sum | avg -------+-----+--------------------- 8 | 330 | 55.5000000000000000 (1 row) -- ORDER BY expression is part of the target list but not pushed down to -- foreign server. --Testcase 208: explain (verbose, costs off) select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1; QUERY PLAN -------------------------------------------------------------------------------- Sort Output: (((sum(c2)) * ((random() <= '1'::double precision))::integer)) Sort Key: (((sum(ft1.c2)) * ((random() <= '1'::double precision))::integer)) -> Foreign Scan Output: ((sum(c2)) * ((random() <= '1'::double precision))::integer) SQLite query: SELECT sum(`c2`) FROM main."T 1" (6 rows) --Testcase 209: select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1; sum ------ 4500 (1 row) -- LATERAL join, with parameterization set enable_hashagg to false; --Testcase 210: explain (verbose, costs off) select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------ Nested Loop Output: t1.c2, qry.sum -> Foreign Scan on "S 1"."T 1" t1 Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) AND ((`C 1` < 100)) ORDER BY `c2` ASC NULLS LAST -> Subquery Scan on qry Output: qry.sum, t2.c1 Filter: (((t1.c2 * 2))::numeric = qry.sum) -> Foreign Scan Output: (sum((t2.c1 + t1."C 1"))), t2.c1 SQLite query: SELECT sum((`C 1` + ?)), `C 1` FROM main."T 1" GROUP BY 2 (11 rows) --Testcase 211: select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1; c2 | sum ----+----- 1 | 2 2 | 4 (2 rows) reset enable_hashagg; -- bug #15613: bad plan for foreign table scan with lateral reference --Testcase 546: EXPLAIN (VERBOSE, COSTS OFF) SELECT ref_0.c2, subq_1.* FROM "S 1"."T 1" AS ref_0, LATERAL ( SELECT ref_0."C 1" c1, subq_0.* FROM (SELECT ref_0.c2, ref_1.c3 FROM ft1 AS ref_1) AS subq_0 RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3) ) AS subq_1 WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001' ORDER BY ref_0."C 1"; QUERY PLAN ------------------------------------------------------------------------------------------------------------- Nested Loop Output: ref_0.c2, ref_0."C 1", (ref_0.c2), ref_1.c3, ref_0."C 1" -> Foreign Scan on "S 1"."T 1" ref_0 Output: ref_0."C 1", ref_0.c2, ref_0.c3, ref_0.c4, ref_0.c5, ref_0.c6, ref_0.c7, ref_0.c8 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` < 10)) ORDER BY `C 1` ASC NULLS LAST -> Nested Loop Output: ref_1.c3, (ref_0.c2) -> Foreign Scan on public.ft2 ref_3 Output: ref_3.c3 SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`c3` = '00001')) -> Materialize Output: ref_1.c3, (ref_0.c2) -> Foreign Scan on public.ft1 ref_1 Output: ref_1.c3, ref_0.c2 SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`c3` = '00001')) (15 rows) --Testcase 547: SELECT ref_0.c2, subq_1.* FROM "S 1"."T 1" AS ref_0, LATERAL ( SELECT ref_0."C 1" c1, subq_0.* FROM (SELECT ref_0.c2, ref_1.c3 FROM ft1 AS ref_1) AS subq_0 RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3) ) AS subq_1 WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001' ORDER BY ref_0."C 1"; c2 | c1 | c2 | c3 ----+----+----+------- 1 | 1 | 1 | 00001 2 | 2 | 2 | 00001 3 | 3 | 3 | 00001 4 | 4 | 4 | 00001 5 | 5 | 5 | 00001 6 | 6 | 6 | 00001 7 | 7 | 7 | 00001 8 | 8 | 8 | 00001 9 | 9 | 9 | 00001 (9 rows) -- Check with placeHolderVars --Testcase 212: explain (verbose, costs off) select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b); QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------- Aggregate Output: sum(q.a), count(q.b) -> Nested Loop Left Join Output: q.a, q.b Inner Unique: true Join Filter: ((ft4.c1)::numeric <= q.b) -> Foreign Scan on public.ft4 Output: ft4.c1, ft4.c2, ft4.c3 SQLite query: SELECT `c1` FROM main."T 3" -> Materialize Output: q.a, q.b -> Subquery Scan on q Output: q.a, q.b -> Foreign Scan Output: 13, (avg(ft1.c1)), NULL::bigint SQLite query: SELECT 13, avg(r1.`C 1`), NULL FROM (main."T 1" r2 LEFT JOIN main."T 1" r1 ON (((r1.`C 1` = r2.`C 1`)))) (16 rows) --Testcase 213: select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b); sum | count -----+------- 650 | 50 (1 row) -- Not supported cases -- Grouping sets --Testcase 214: explain (verbose, costs off) select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last; QUERY PLAN ---------------------------------------------------------------------------------------------------------- GroupAggregate Output: c2, sum(c1) Group Key: ft1.c2 Group Key: () -> Foreign Scan on public.ft1 Output: c2, c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST (7 rows) --Testcase 215: select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last; c2 | sum ----+-------- 0 | 50500 1 | 49600 2 | 49700 | 149800 (4 rows) --Testcase 216: explain (verbose, costs off) select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last; QUERY PLAN ---------------------------------------------------------------------------------------------------------- GroupAggregate Output: c2, sum(c1) Group Key: ft1.c2 Group Key: () -> Foreign Scan on public.ft1 Output: c2, c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST (7 rows) --Testcase 217: select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last; c2 | sum ----+-------- 0 | 50500 1 | 49600 2 | 49700 | 149800 (4 rows) --Testcase 218: explain (verbose, costs off) select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------- Sort Output: c2, c6, (sum(c1)) Sort Key: ft1.c2, ft1.c6 -> MixedAggregate Output: c2, c6, sum(c1) Hash Key: ft1.c6 Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c2, c6, c1 SQLite query: SELECT `C 1`, `c2`, `c6` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST (10 rows) --Testcase 219: select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last; c2 | c6 | sum ----+----+------- 0 | | 50500 1 | | 49600 2 | | 49700 | 0 | 50500 | 1 | 49600 | 2 | 49700 (6 rows) --Testcase 220: explain (verbose, costs off) select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last; QUERY PLAN ---------------------------------------------------------------------------------------------------------- GroupAggregate Output: c2, sum(c1), GROUPING(c2) Group Key: ft1.c2 -> Foreign Scan on public.ft1 Output: c2, c1 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`c2` < 3)) ORDER BY `c2` ASC NULLS LAST (6 rows) --Testcase 221: select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last; c2 | sum | grouping ----+-------+---------- 0 | 50500 | 0 1 | 49600 | 0 2 | 49700 | 0 (3 rows) -- DISTINCT itself is not pushed down, whereas underneath aggregate is pushed --Testcase 222: explain (verbose, costs off) select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1; QUERY PLAN ------------------------------------------------------------------------------------------------------------ Unique Output: ((sum(c1) / 1000)), c2 -> Sort Output: ((sum(c1) / 1000)), c2 Sort Key: ((sum(ft2.c1) / 1000)) -> Foreign Scan Output: ((sum(c1) / 1000)), c2 SQLite query: SELECT (sum(`C 1`) / 1000), `c2` FROM main."T 1" WHERE ((`c2` < 6)) GROUP BY 2 (8 rows) --Testcase 223: select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1; s ---- 49 50 (2 rows) -- WindowAgg --Testcase 224: explain (verbose, costs off) select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; QUERY PLAN --------------------------------------------------------------------------------------------------------------------- Sort Output: c2, (sum(c2)), (count(c2) OVER (?)), ((c2 % 2)) Sort Key: ft2.c2 -> WindowAgg Output: c2, (sum(c2)), count(c2) OVER (?), ((c2 % 2)) -> Sort Output: c2, ((c2 % 2)), (sum(c2)) Sort Key: ((ft2.c2 % 2)) -> Foreign Scan Output: c2, ((c2 % 2)), (sum(c2)) SQLite query: SELECT `c2`, (`c2` % 2), sum(`c2`) FROM main."T 1" WHERE ((`c2` < 10)) GROUP BY 1 (11 rows) --Testcase 225: select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1; c2 | sum | count ----+-----+------- 0 | 0 | 5 1 | 100 | 5 2 | 200 | 5 3 | 300 | 5 4 | 400 | 5 5 | 500 | 5 6 | 600 | 5 7 | 700 | 5 8 | 800 | 5 9 | 900 | 5 (10 rows) --Testcase 226: explain (verbose, costs off) select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; QUERY PLAN ---------------------------------------------------------------------------------------------------------- Sort Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2)) Sort Key: ft1.c2 -> WindowAgg Output: c2, array_agg(c2) OVER (?), ((c2 % 2)) -> Sort Output: c2, ((c2 % 2)) Sort Key: ((ft1.c2 % 2)), ft1.c2 DESC -> Foreign Scan Output: c2, ((c2 % 2)) SQLite query: SELECT `c2`, (`c2` % 2) FROM main."T 1" WHERE ((`c2` < 10)) GROUP BY 1 (11 rows) --Testcase 227: select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1; c2 | array_agg ----+------------- 0 | {8,6,4,2,0} 1 | {9,7,5,3,1} 2 | {8,6,4,2} 3 | {9,7,5,3} 4 | {8,6,4} 5 | {9,7,5} 6 | {8,6} 7 | {9,7} 8 | {8} 9 | {9} (10 rows) --Testcase 228: explain (verbose, costs off) select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; QUERY PLAN ---------------------------------------------------------------------------------------------------------- Sort Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2)) Sort Key: ft1.c2 -> WindowAgg Output: c2, array_agg(c2) OVER (?), ((c2 % 2)) -> Sort Output: c2, ((c2 % 2)) Sort Key: ((ft1.c2 % 2)), ft1.c2 -> Foreign Scan Output: c2, ((c2 % 2)) SQLite query: SELECT `c2`, (`c2` % 2) FROM main."T 1" WHERE ((`c2` < 10)) GROUP BY 1 (11 rows) --Testcase 229: select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1; c2 | array_agg ----+------------- 0 | {0,2,4,6,8} 1 | {1,3,5,7,9} 2 | {2,4,6,8} 3 | {3,5,7,9} 4 | {4,6,8} 5 | {5,7,9} 6 | {6,8} 7 | {7,9} 8 | {8} 9 | {9} (10 rows) -- =================================================================== -- parameterized queries -- =================================================================== -- simple join --Testcase 230: PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $1 AND t2.c1 = $2; --Testcase 231: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2); QUERY PLAN ----------------------------------------------------------------------------- Nested Loop Output: t1.c3, t2.c3 -> Foreign Scan on public.ft1 t1 Output: t1.c3 SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`C 1` = 1)) -> Materialize Output: t2.c3 -> Foreign Scan on public.ft2 t2 Output: t2.c3 SQLite query: SELECT `c3` FROM main."T 1" WHERE ((`C 1` = 2)) (10 rows) --Testcase 232: EXECUTE st1(1, 1); c3 | c3 -------+------- 00001 | 00001 (1 row) --Testcase 233: EXECUTE st1(101, 101); c3 | c3 -------+------- 00101 | 00101 (1 row) -- subquery using stable function (can't be sent to remote) --Testcase 234: PREPARE st2(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c4) = '1970-01-17'::date) ORDER BY c1; --Testcase 235: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st2(10, 20); QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------- Sort Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 Sort Key: t1.c1 -> Hash Semi Join Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 Hash Cond: (t1.c3 = t2.c3) -> Foreign Scan on public.ft1 t1 Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 20)) ORDER BY `C 1` ASC NULLS LAST -> Hash Output: t2.c3 -> Foreign Scan on public.ft2 t2 Output: t2.c3 Filter: (date(t2.c4) = '01-17-1970'::date) SQLite query: SELECT `c3`, `c4` FROM main."T 1" WHERE ((`C 1` > 10)) (15 rows) --Testcase 236: EXECUTE st2(10, 20); c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo (1 row) --Testcase 237: EXECUTE st2(101, 121); c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 -----+----+-------+------------------------------+--------------------------+----+------------+----- 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo (1 row) -- subquery using immutable function (can be sent to remote) --Testcase 238: PREPARE st3(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c5) = '1970-01-17'::date) ORDER BY c1; --Testcase 239: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st3(10, 20); QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------- Sort Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 Sort Key: t1.c1 -> Hash Semi Join Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 Hash Cond: (t1.c3 = t2.c3) -> Foreign Scan on public.ft1 t1 Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` < 20)) ORDER BY `C 1` ASC NULLS LAST -> Hash Output: t2.c3 -> Foreign Scan on public.ft2 t2 Output: t2.c3 Filter: (date(t2.c5) = '01-17-1970'::date) SQLite query: SELECT `c3`, `c5` FROM main."T 1" WHERE ((`C 1` > 10)) (15 rows) --Testcase 240: EXECUTE st3(10, 20); c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo (1 row) --Testcase 241: EXECUTE st3(20, 30); c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+----+----+----+----+----+---- (0 rows) -- custom plan should be chosen initially --Testcase 242: PREPARE st4(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 = $1; --Testcase 243: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); QUERY PLAN ------------------------------------------------------------------------------------------------------------ Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) (3 rows) --Testcase 244: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); QUERY PLAN ------------------------------------------------------------------------------------------------------------ Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) (3 rows) --Testcase 245: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); QUERY PLAN ------------------------------------------------------------------------------------------------------------ Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) (3 rows) --Testcase 246: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); QUERY PLAN ------------------------------------------------------------------------------------------------------------ Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) (3 rows) --Testcase 247: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); QUERY PLAN ------------------------------------------------------------------------------------------------------------ Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = 1)) (3 rows) -- once we try it enough times, should switch to generic plan --Testcase 248: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1); QUERY PLAN ------------------------------------------------------------------------------------------------------------ Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = ?)) (3 rows) -- value of $1 should not be sent to remote --Testcase 249: PREPARE st5(text,int) AS SELECT * FROM ft1 t1 WHERE c8 = $1 and c1 = $2; --Testcase 250: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) (3 rows) --Testcase 251: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) (3 rows) --Testcase 252: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) (3 rows) --Testcase 253: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) (3 rows) --Testcase 254: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = 'foo')) AND ((`C 1` = 1)) (3 rows) --Testcase 255: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1); QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`c8` = ?)) AND ((`C 1` = ?)) (3 rows) --Testcase 256: EXECUTE st5('foo', 1); c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo (1 row) -- altering FDW options requires replanning --Testcase 257: PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2; --Testcase 258: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; QUERY PLAN --------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` = `c2`)) (3 rows) --Testcase 259: PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo'); --Testcase 260: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Insert on public.ft1 Batch Size: 1 -> Result Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::text (4 rows) --Testcase 548: INSERT INTO "S 1"."T 0" SELECT * FROM "S 1"."T 1"; ALTER FOREIGN TABLE ft1 OPTIONS (SET table 'T 0'); --Testcase 261: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6; QUERY PLAN --------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 0" WHERE ((`C 1` = `c2`)) (3 rows) --Testcase 262: EXECUTE st6; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo (9 rows) --Testcase 263: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7; QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Insert on public.ft1 Batch Size: 1 -> Result Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::text (4 rows) ALTER FOREIGN TABLE ft1 OPTIONS (SET table 'T 1'); --Testcase 549: PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2; --Testcase 550: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8; QUERY PLAN ---------------------------------------------------------------- Aggregate Output: count(c3) -> Foreign Scan on public.ft1 t1 Output: c3 Filter: (t1.c1 === t1.c2) SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" (6 rows) --ALTER SERVER loopback OPTIONS (DROP extensions); --Testcase 551: EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8; QUERY PLAN ---------------------------------------------------------------- Aggregate Output: count(c3) -> Foreign Scan on public.ft1 t1 Output: c3 Filter: (t1.c1 === t1.c2) SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" (6 rows) --Testcase 552: EXECUTE st8; count ------- 9 (1 row) --ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); -- cleanup DEALLOCATE st1; DEALLOCATE st2; DEALLOCATE st3; DEALLOCATE st4; DEALLOCATE st5; DEALLOCATE st6; DEALLOCATE st7; DEALLOCATE st8; -- System columns, except ctid and oid, should not be sent to remote --Testcase 264: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1; QUERY PLAN ---------------------------------------------------------------------------------------------- Limit Output: c1, c2, c3, c4, c5, c6, c7, c8 -> Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 Filter: (t1.tableoid = '1259'::oid) SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (6 rows) --Testcase 265: SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo (1 row) --Testcase 266: EXPLAIN (VERBOSE, COSTS OFF) SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1; QUERY PLAN ------------------------------------------------------------------------------------------------ Foreign Scan on public.ft1 t1 Output: (tableoid)::regclass, c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" LIMIT 1 (3 rows) --Testcase 267: SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1; tableoid | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----------+----+----+-------+------------------------------+--------------------------+----+------------+----- ft1 | 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo (1 row) --Testcase 268: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)'; QUERY PLAN ---------------------------------------------------------------------------------------- Foreign Scan on public.ft1 t1 Output: c1, c2, c3, c4, c5, c6, c7, c8 Filter: (t1.ctid = '(0,2)'::tid) SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (4 rows) --Testcase 553: SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)'; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+----+----+----+----+----+---- (0 rows) --Testcase 554: EXPLAIN (VERBOSE, COSTS OFF) SELECT ctid, * FROM ft1 t1 LIMIT 1; QUERY PLAN ------------------------------------------------------------------------------------------------ Foreign Scan on public.ft1 t1 Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" LIMIT 1 (3 rows) --Testcase 271: SELECT ctid, * FROM ft1 t1 LIMIT 1; ctid | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----------------+----+----+-------+------------------------------+--------------------------+----+------------+----- (4294967295,0) | 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo (1 row) -- =================================================================== -- used in PL/pgSQL function -- =================================================================== --Testcase 555: CREATE OR REPLACE FUNCTION f_test(p_c1 int) RETURNS int AS $$ DECLARE v_c1 int; BEGIN --Testcase 556: SELECT c1 INTO v_c1 FROM ft1 WHERE c1 = p_c1 LIMIT 1; PERFORM c1 FROM ft1 WHERE c1 = p_c1 AND p_c1 = v_c1 LIMIT 1; RETURN v_c1; END; $$ LANGUAGE plpgsql; --Testcase 272: SELECT f_test(100); f_test -------- 100 (1 row) --Testcase 557: DROP FUNCTION f_test(int); -- =================================================================== -- REINDEX -- =================================================================== -- remote table is not created here CREATE FOREIGN TABLE reindex_foreign (c1 int, c2 int) SERVER sqlite_svr2 OPTIONS (table 'reindex_local'); REINDEX TABLE reindex_foreign; -- error ERROR: "reindex_foreign" is not a table or materialized view REINDEX TABLE CONCURRENTLY reindex_foreign; -- error ERROR: "reindex_foreign" is not a table or materialized view DROP FOREIGN TABLE reindex_foreign; -- partitions and foreign tables CREATE TABLE reind_fdw_parent (c1 int) PARTITION BY RANGE (c1); CREATE TABLE reind_fdw_0_10 PARTITION OF reind_fdw_parent FOR VALUES FROM (0) TO (10); CREATE FOREIGN TABLE reind_fdw_10_20 PARTITION OF reind_fdw_parent FOR VALUES FROM (10) TO (20) SERVER sqlite_svr OPTIONS (table 'reind_local_10_20'); REINDEX TABLE reind_fdw_parent; -- ok REINDEX TABLE CONCURRENTLY reind_fdw_parent; -- ok DROP TABLE reind_fdw_parent; -- =================================================================== -- conversion error -- =================================================================== ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int; --Testcase 273: SELECT * FROM ft1 WHERE c1 = 1; ERROR: invalid input syntax for type =1, column type =3 --Testcase 274: SELECT ft1.c1, ft2.c2, ft1.c8 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; ERROR: invalid input syntax for type =1, column type =3 --Testcase 275: SELECT ft1.c1, ft2.c2, ft1 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; ERROR: invalid input syntax for type =1, column type =3 --Testcase 276: SELECT sum(c2), array_agg(c8) FROM ft1 GROUP BY c8; ERROR: invalid input syntax for type =1, column type =3 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE text; -- =================================================================== -- subtransaction -- + local/remote error doesn't break cursor -- =================================================================== BEGIN; DECLARE c CURSOR FOR SELECT * FROM ft1 ORDER BY c1; --Testcase 277: FETCH c; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo (1 row) SAVEPOINT s; ERROR OUT; -- ERROR ERROR: syntax error at or near "ERROR" LINE 1: ERROR OUT; ^ ROLLBACK TO s; --Testcase 278: FETCH c; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo (1 row) SAVEPOINT s; --Testcase 279: SELECT * FROM ft1 WHERE 1 / (c1 - 1) > 0; -- ERROR c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo (1 row) ROLLBACK TO s; --Testcase 280: FETCH c; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo (1 row) --Testcase 281: SELECT * FROM ft1 ORDER BY c1 LIMIT 1; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ----+----+-------+------------------------------+--------------------------+----+------------+----- 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo (1 row) COMMIT; -- =================================================================== -- test handling of collations -- =================================================================== --Testcase 558: create foreign table ft3 (f1 text collate "C", f2 text, f3 varchar(10)) server sqlite_svr; -- can be sent to remote --Testcase 559: explain (verbose, costs off) select * from ft3 where f1 = 'foo'; QUERY PLAN -------------------------------------------------------------------------------- Foreign Scan on public.ft3 Output: f1, f2, f3 SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f1` = 'foo')) (3 rows) --Testcase 560: explain (verbose, costs off) select * from ft3 where f1 COLLATE "C" = 'foo'; QUERY PLAN -------------------------------------------------------------------------------- Foreign Scan on public.ft3 Output: f1, f2, f3 SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f1` = 'foo')) (3 rows) --Testcase 561: explain (verbose, costs off) select * from ft3 where f2 = 'foo'; QUERY PLAN -------------------------------------------------------------------------------- Foreign Scan on public.ft3 Output: f1, f2, f3 SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f2` = 'foo')) (3 rows) --Testcase 562: explain (verbose, costs off) select * from ft3 where f3 = 'foo'; QUERY PLAN -------------------------------------------------------------------------------- Foreign Scan on public.ft3 Output: f1, f2, f3 SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" WHERE ((`f3` = 'foo')) (3 rows) --Testcase 563: explain (verbose, costs off) select * from ft3 f, loct3 l where f.f3 = l.f3 and l.f1 = 'foo'; ERROR: relation "loct3" does not exist LINE 1: explain (verbose, costs off) select * from ft3 f, loct3 l ^ -- can't be sent to remote --Testcase 564: explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo'; QUERY PLAN --------------------------------------------------------- Foreign Scan on public.ft3 Output: f1, f2, f3 Filter: ((ft3.f1)::text = 'foo'::text) SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" (4 rows) --Testcase 565: explain (verbose, costs off) select * from ft3 where f1 = 'foo' COLLATE "C"; QUERY PLAN --------------------------------------------------------- Foreign Scan on public.ft3 Output: f1, f2, f3 Filter: (ft3.f1 = 'foo'::text COLLATE "C") SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" (4 rows) --Testcase 566: explain (verbose, costs off) select * from ft3 where f2 COLLATE "C" = 'foo'; QUERY PLAN --------------------------------------------------------- Foreign Scan on public.ft3 Output: f1, f2, f3 Filter: ((ft3.f2)::text = 'foo'::text) SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" (4 rows) --Testcase 567: explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C"; QUERY PLAN --------------------------------------------------------- Foreign Scan on public.ft3 Output: f1, f2, f3 Filter: (ft3.f2 = 'foo'::text COLLATE "C") SQLite query: SELECT `f1`, `f2`, `f3` FROM main."ft3" (4 rows) --Testcase 568: explain (verbose, costs off) select * from ft3 f, loct3 l where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo'; ERROR: relation "loct3" does not exist LINE 1: explain (verbose, costs off) select * from ft3 f, loct3 l ^ -- =================================================================== -- test writable foreign table stuff -- =================================================================== --Testcase 282: EXPLAIN (verbose, costs off) INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Insert on public.ft2 Batch Size: 1 -> Subquery Scan on "*SELECT*" Output: "*SELECT*"."?column?", "*SELECT*"."?column?_1", NULL::integer, "*SELECT*"."?column?_2", NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2 '::character(10), NULL::text -> Foreign Scan on public.ft2 ft2_1 Output: (ft2_1.c1 + 1000), (ft2_1.c2 + 100), (ft2_1.c3 || ft2_1.c3) SQLite query: SELECT `C 1`, `c2`, `c3` FROM main."T 1" LIMIT 20 (7 rows) --Testcase 283: INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20; --Testcase 284: INSERT INTO ft2 (c1,c2,c3) VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc'); --Testcase 285: SELECT * FROM ft2 WHERE c1 >= 1101; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+-----+-----+----+----+----+------------+---- 1101 | 201 | aaa | | | | ft2 | 1102 | 202 | bbb | | | | ft2 | 1103 | 203 | ccc | | | | ft2 | (3 rows) --Testcase 286: INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee'); --Testcase 287: EXPLAIN (verbose, costs off) UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; -- can be pushed down QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- Update on public.ft2 -> Foreign Update on public.ft2 SQLite query: UPDATE main."T 1" SET `c2` = (`c2` + 300), `c3` = (`c3` || '_update3') WHERE (((`C 1` % 10) = 3)) (3 rows) --Testcase 288: UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; --Testcase 289: EXPLAIN (verbose, costs off) UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7; -- can be pushed down QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- Update on public.ft2 -> Foreign Update on public.ft2 SQLite query: UPDATE main."T 1" SET `c2` = (`c2` + 400), `c3` = (`c3` || '_update7') WHERE (((`C 1` % 10) = 7)) (3 rows) --Testcase 290: UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7; --Testcase 291: SELECT * FROM ft2 WHERE c1 % 10 = 7; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+-----+--------------------+------------------------------+--------------------------+----+------------+----- 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo 47 | 407 | 00047_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo 57 | 407 | 00057_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo 67 | 407 | 00067_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo 77 | 407 | 00077_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo 87 | 407 | 00087_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo 97 | 407 | 00097_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo 107 | 407 | 00107_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 117 | 407 | 00117_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo 127 | 407 | 00127_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo 137 | 407 | 00137_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo 147 | 407 | 00147_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo 157 | 407 | 00157_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo 167 | 407 | 00167_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo 177 | 407 | 00177_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo 187 | 407 | 00187_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo 197 | 407 | 00197_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo 207 | 407 | 00207_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 217 | 407 | 00217_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo 227 | 407 | 00227_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo 237 | 407 | 00237_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo 247 | 407 | 00247_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo 257 | 407 | 00257_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo 267 | 407 | 00267_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo 277 | 407 | 00277_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo 287 | 407 | 00287_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo 297 | 407 | 00297_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo 307 | 407 | 00307_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 317 | 407 | 00317_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo 327 | 407 | 00327_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo 337 | 407 | 00337_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo 347 | 407 | 00347_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo 357 | 407 | 00357_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo 367 | 407 | 00367_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo 377 | 407 | 00377_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo 387 | 407 | 00387_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo 397 | 407 | 00397_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo 407 | 407 | 00407_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 417 | 407 | 00417_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo 427 | 407 | 00427_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo 437 | 407 | 00437_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo 447 | 407 | 00447_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo 457 | 407 | 00457_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo 467 | 407 | 00467_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo 477 | 407 | 00477_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo 487 | 407 | 00487_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo 497 | 407 | 00497_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo 507 | 407 | 00507_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 517 | 407 | 00517_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo 527 | 407 | 00527_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo 537 | 407 | 00537_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo 547 | 407 | 00547_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo 557 | 407 | 00557_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo 567 | 407 | 00567_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo 577 | 407 | 00577_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo 587 | 407 | 00587_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo 597 | 407 | 00597_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo 607 | 407 | 00607_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 617 | 407 | 00617_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo 627 | 407 | 00627_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo 637 | 407 | 00637_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo 647 | 407 | 00647_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo 657 | 407 | 00657_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo 667 | 407 | 00667_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo 677 | 407 | 00677_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo 687 | 407 | 00687_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo 697 | 407 | 00697_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo 707 | 407 | 00707_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 717 | 407 | 00717_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo 727 | 407 | 00727_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo 737 | 407 | 00737_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo 747 | 407 | 00747_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo 757 | 407 | 00757_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo 767 | 407 | 00767_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo 777 | 407 | 00777_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo 787 | 407 | 00787_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo 797 | 407 | 00797_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo 807 | 407 | 00807_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 817 | 407 | 00817_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo 827 | 407 | 00827_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo 837 | 407 | 00837_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo 847 | 407 | 00847_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo 857 | 407 | 00857_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo 867 | 407 | 00867_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo 877 | 407 | 00877_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo 887 | 407 | 00887_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo 897 | 407 | 00897_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo 907 | 407 | 00907_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo 917 | 407 | 00917_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo 927 | 407 | 00927_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo 937 | 407 | 00937_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo 947 | 407 | 00947_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo 957 | 407 | 00957_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo 967 | 407 | 00967_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo 977 | 407 | 00977_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo 987 | 407 | 00987_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo 997 | 407 | 00997_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo 1007 | 507 | 0000700007_update7 | | | | ft2 | 1017 | 507 | 0001700017_update7 | | | | ft2 | (102 rows) --Testcase 292: EXPLAIN (verbose, costs off) UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Update on public.ft2 -> Foreign Scan Output: (ft2.c2 + 500), (ft2.c3 || '_update9'::text), 'ft2 '::character(10), ft2.c1, ft2.*, ft1.* SQLite query: SELECT r1.`c2`, r1.`c3`, r1.`C 1`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`c2` = r2.`C 1`)) AND (((r2.`C 1` % 10) = 9)))) -> Hash Join Output: ft2.c2, ft2.c3, ft2.c1, ft2.*, ft1.* Hash Cond: (ft2.c2 = ft1.c1) -> Foreign Scan on public.ft2 Output: ft2.c2, ft2.c3, ft2.c1, ft2.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" -> Hash Output: ft1.*, ft1.c1 -> Foreign Scan on public.ft1 Output: ft1.*, ft1.c1 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (((`C 1` % 10) = 9)) (15 rows) --Testcase 293: UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; --Testcase 294: EXPLAIN (verbose, costs off) DELETE FROM ft2 WHERE c1 % 10 = 5; -- can be pushed down QUERY PLAN ------------------------------------------------------------------------- Delete on public.ft2 -> Foreign Delete on public.ft2 SQLite query: DELETE FROM main."T 1" WHERE (((`C 1` % 10) = 5)) (3 rows) --Testcase 295: SELECT c1, c4 FROM ft2 WHERE c1 % 10 = 5; c1 | c4 ------+------------------------------ 5 | Tue Jan 06 00:00:00 1970 PST 15 | Fri Jan 16 00:00:00 1970 PST 25 | Mon Jan 26 00:00:00 1970 PST 35 | Thu Feb 05 00:00:00 1970 PST 45 | Sun Feb 15 00:00:00 1970 PST 55 | Wed Feb 25 00:00:00 1970 PST 65 | Sat Mar 07 00:00:00 1970 PST 75 | Tue Mar 17 00:00:00 1970 PST 85 | Fri Mar 27 00:00:00 1970 PST 95 | Mon Apr 06 00:00:00 1970 PST 105 | Tue Jan 06 00:00:00 1970 PST 115 | Fri Jan 16 00:00:00 1970 PST 125 | Mon Jan 26 00:00:00 1970 PST 135 | Thu Feb 05 00:00:00 1970 PST 145 | Sun Feb 15 00:00:00 1970 PST 155 | Wed Feb 25 00:00:00 1970 PST 165 | Sat Mar 07 00:00:00 1970 PST 175 | Tue Mar 17 00:00:00 1970 PST 185 | Fri Mar 27 00:00:00 1970 PST 195 | Mon Apr 06 00:00:00 1970 PST 205 | Tue Jan 06 00:00:00 1970 PST 215 | Fri Jan 16 00:00:00 1970 PST 225 | Mon Jan 26 00:00:00 1970 PST 235 | Thu Feb 05 00:00:00 1970 PST 245 | Sun Feb 15 00:00:00 1970 PST 255 | Wed Feb 25 00:00:00 1970 PST 265 | Sat Mar 07 00:00:00 1970 PST 275 | Tue Mar 17 00:00:00 1970 PST 285 | Fri Mar 27 00:00:00 1970 PST 295 | Mon Apr 06 00:00:00 1970 PST 305 | Tue Jan 06 00:00:00 1970 PST 315 | Fri Jan 16 00:00:00 1970 PST 325 | Mon Jan 26 00:00:00 1970 PST 335 | Thu Feb 05 00:00:00 1970 PST 345 | Sun Feb 15 00:00:00 1970 PST 355 | Wed Feb 25 00:00:00 1970 PST 365 | Sat Mar 07 00:00:00 1970 PST 375 | Tue Mar 17 00:00:00 1970 PST 385 | Fri Mar 27 00:00:00 1970 PST 395 | Mon Apr 06 00:00:00 1970 PST 405 | Tue Jan 06 00:00:00 1970 PST 415 | Fri Jan 16 00:00:00 1970 PST 425 | Mon Jan 26 00:00:00 1970 PST 435 | Thu Feb 05 00:00:00 1970 PST 445 | Sun Feb 15 00:00:00 1970 PST 455 | Wed Feb 25 00:00:00 1970 PST 465 | Sat Mar 07 00:00:00 1970 PST 475 | Tue Mar 17 00:00:00 1970 PST 485 | Fri Mar 27 00:00:00 1970 PST 495 | Mon Apr 06 00:00:00 1970 PST 505 | Tue Jan 06 00:00:00 1970 PST 515 | Fri Jan 16 00:00:00 1970 PST 525 | Mon Jan 26 00:00:00 1970 PST 535 | Thu Feb 05 00:00:00 1970 PST 545 | Sun Feb 15 00:00:00 1970 PST 555 | Wed Feb 25 00:00:00 1970 PST 565 | Sat Mar 07 00:00:00 1970 PST 575 | Tue Mar 17 00:00:00 1970 PST 585 | Fri Mar 27 00:00:00 1970 PST 595 | Mon Apr 06 00:00:00 1970 PST 605 | Tue Jan 06 00:00:00 1970 PST 615 | Fri Jan 16 00:00:00 1970 PST 625 | Mon Jan 26 00:00:00 1970 PST 635 | Thu Feb 05 00:00:00 1970 PST 645 | Sun Feb 15 00:00:00 1970 PST 655 | Wed Feb 25 00:00:00 1970 PST 665 | Sat Mar 07 00:00:00 1970 PST 675 | Tue Mar 17 00:00:00 1970 PST 685 | Fri Mar 27 00:00:00 1970 PST 695 | Mon Apr 06 00:00:00 1970 PST 705 | Tue Jan 06 00:00:00 1970 PST 715 | Fri Jan 16 00:00:00 1970 PST 725 | Mon Jan 26 00:00:00 1970 PST 735 | Thu Feb 05 00:00:00 1970 PST 745 | Sun Feb 15 00:00:00 1970 PST 755 | Wed Feb 25 00:00:00 1970 PST 765 | Sat Mar 07 00:00:00 1970 PST 775 | Tue Mar 17 00:00:00 1970 PST 785 | Fri Mar 27 00:00:00 1970 PST 795 | Mon Apr 06 00:00:00 1970 PST 805 | Tue Jan 06 00:00:00 1970 PST 815 | Fri Jan 16 00:00:00 1970 PST 825 | Mon Jan 26 00:00:00 1970 PST 835 | Thu Feb 05 00:00:00 1970 PST 845 | Sun Feb 15 00:00:00 1970 PST 855 | Wed Feb 25 00:00:00 1970 PST 865 | Sat Mar 07 00:00:00 1970 PST 875 | Tue Mar 17 00:00:00 1970 PST 885 | Fri Mar 27 00:00:00 1970 PST 895 | Mon Apr 06 00:00:00 1970 PST 905 | Tue Jan 06 00:00:00 1970 PST 915 | Fri Jan 16 00:00:00 1970 PST 925 | Mon Jan 26 00:00:00 1970 PST 935 | Thu Feb 05 00:00:00 1970 PST 945 | Sun Feb 15 00:00:00 1970 PST 955 | Wed Feb 25 00:00:00 1970 PST 965 | Sat Mar 07 00:00:00 1970 PST 975 | Tue Mar 17 00:00:00 1970 PST 985 | Fri Mar 27 00:00:00 1970 PST 995 | Mon Apr 06 00:00:00 1970 PST 1005 | 1015 | 1105 | (103 rows) --Testcase 569: DELETE FROM ft2 WHERE c1 % 10 = 5; --Testcase 297: EXPLAIN (verbose, costs off) DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down QUERY PLAN ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Delete on public.ft2 -> Foreign Scan Output: ft2.c1, ft1.* SQLite query: SELECT r1.`C 1`, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`c2` = r2.`C 1`)) AND (((r2.`C 1` % 10) = 2)))) -> Hash Join Output: ft2.c1, ft1.* Hash Cond: (ft2.c2 = ft1.c1) -> Foreign Scan on public.ft2 Output: ft2.c1, ft2.c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" -> Hash Output: ft1.*, ft1.c1 -> Foreign Scan on public.ft1 Output: ft1.*, ft1.c1 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE (((`C 1` % 10) = 2)) (15 rows) --Testcase 298: DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; --Testcase 299: SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1; c1 | c2 | c3 | c4 ------+-----+--------------------+------------------------------ 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST 3 | 303 | 00003_update3 | Sun Jan 04 00:00:00 1970 PST 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST 9 | 509 | 00009_update9 | Sat Jan 10 00:00:00 1970 PST 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST 11 | 1 | 00011 | Mon Jan 12 00:00:00 1970 PST 13 | 303 | 00013_update3 | Wed Jan 14 00:00:00 1970 PST 14 | 4 | 00014 | Thu Jan 15 00:00:00 1970 PST 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST 18 | 8 | 00018 | Mon Jan 19 00:00:00 1970 PST 19 | 509 | 00019_update9 | Tue Jan 20 00:00:00 1970 PST 20 | 0 | 00020 | Wed Jan 21 00:00:00 1970 PST 21 | 1 | 00021 | Thu Jan 22 00:00:00 1970 PST 23 | 303 | 00023_update3 | Sat Jan 24 00:00:00 1970 PST 24 | 4 | 00024 | Sun Jan 25 00:00:00 1970 PST 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST 28 | 8 | 00028 | Thu Jan 29 00:00:00 1970 PST 29 | 509 | 00029_update9 | Fri Jan 30 00:00:00 1970 PST 30 | 0 | 00030 | Sat Jan 31 00:00:00 1970 PST 31 | 1 | 00031 | Sun Feb 01 00:00:00 1970 PST 33 | 303 | 00033_update3 | Tue Feb 03 00:00:00 1970 PST 34 | 4 | 00034 | Wed Feb 04 00:00:00 1970 PST 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST 38 | 8 | 00038 | Sun Feb 08 00:00:00 1970 PST 39 | 509 | 00039_update9 | Mon Feb 09 00:00:00 1970 PST 40 | 0 | 00040 | Tue Feb 10 00:00:00 1970 PST 41 | 1 | 00041 | Wed Feb 11 00:00:00 1970 PST 43 | 303 | 00043_update3 | Fri Feb 13 00:00:00 1970 PST 44 | 4 | 00044 | Sat Feb 14 00:00:00 1970 PST 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST 47 | 407 | 00047_update7 | Tue Feb 17 00:00:00 1970 PST 48 | 8 | 00048 | Wed Feb 18 00:00:00 1970 PST 49 | 509 | 00049_update9 | Thu Feb 19 00:00:00 1970 PST 50 | 0 | 00050 | Fri Feb 20 00:00:00 1970 PST 51 | 1 | 00051 | Sat Feb 21 00:00:00 1970 PST 53 | 303 | 00053_update3 | Mon Feb 23 00:00:00 1970 PST 54 | 4 | 00054 | Tue Feb 24 00:00:00 1970 PST 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST 57 | 407 | 00057_update7 | Fri Feb 27 00:00:00 1970 PST 58 | 8 | 00058 | Sat Feb 28 00:00:00 1970 PST 59 | 509 | 00059_update9 | Sun Mar 01 00:00:00 1970 PST 60 | 0 | 00060 | Mon Mar 02 00:00:00 1970 PST 61 | 1 | 00061 | Tue Mar 03 00:00:00 1970 PST 63 | 303 | 00063_update3 | Thu Mar 05 00:00:00 1970 PST 64 | 4 | 00064 | Fri Mar 06 00:00:00 1970 PST 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST 67 | 407 | 00067_update7 | Mon Mar 09 00:00:00 1970 PST 68 | 8 | 00068 | Tue Mar 10 00:00:00 1970 PST 69 | 509 | 00069_update9 | Wed Mar 11 00:00:00 1970 PST 70 | 0 | 00070 | Thu Mar 12 00:00:00 1970 PST 71 | 1 | 00071 | Fri Mar 13 00:00:00 1970 PST 73 | 303 | 00073_update3 | Sun Mar 15 00:00:00 1970 PST 74 | 4 | 00074 | Mon Mar 16 00:00:00 1970 PST 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST 77 | 407 | 00077_update7 | Thu Mar 19 00:00:00 1970 PST 78 | 8 | 00078 | Fri Mar 20 00:00:00 1970 PST 79 | 509 | 00079_update9 | Sat Mar 21 00:00:00 1970 PST 80 | 0 | 00080 | Sun Mar 22 00:00:00 1970 PST 81 | 1 | 00081 | Mon Mar 23 00:00:00 1970 PST 83 | 303 | 00083_update3 | Wed Mar 25 00:00:00 1970 PST 84 | 4 | 00084 | Thu Mar 26 00:00:00 1970 PST 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST 87 | 407 | 00087_update7 | Sun Mar 29 00:00:00 1970 PST 88 | 8 | 00088 | Mon Mar 30 00:00:00 1970 PST 89 | 509 | 00089_update9 | Tue Mar 31 00:00:00 1970 PST 90 | 0 | 00090 | Wed Apr 01 00:00:00 1970 PST 91 | 1 | 00091 | Thu Apr 02 00:00:00 1970 PST 93 | 303 | 00093_update3 | Sat Apr 04 00:00:00 1970 PST 94 | 4 | 00094 | Sun Apr 05 00:00:00 1970 PST 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST 97 | 407 | 00097_update7 | Wed Apr 08 00:00:00 1970 PST 98 | 8 | 00098 | Thu Apr 09 00:00:00 1970 PST 99 | 509 | 00099_update9 | Fri Apr 10 00:00:00 1970 PST 100 | 0 | 00100 | Thu Jan 01 00:00:00 1970 PST 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST 103 | 303 | 00103_update3 | Sun Jan 04 00:00:00 1970 PST 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST 107 | 407 | 00107_update7 | Thu Jan 08 00:00:00 1970 PST 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST 109 | 509 | 00109_update9 | Sat Jan 10 00:00:00 1970 PST 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST 111 | 1 | 00111 | Mon Jan 12 00:00:00 1970 PST 113 | 303 | 00113_update3 | Wed Jan 14 00:00:00 1970 PST 114 | 4 | 00114 | Thu Jan 15 00:00:00 1970 PST 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST 117 | 407 | 00117_update7 | Sun Jan 18 00:00:00 1970 PST 118 | 8 | 00118 | Mon Jan 19 00:00:00 1970 PST 119 | 509 | 00119_update9 | Tue Jan 20 00:00:00 1970 PST 120 | 0 | 00120 | Wed Jan 21 00:00:00 1970 PST 121 | 1 | 00121 | Thu Jan 22 00:00:00 1970 PST 123 | 303 | 00123_update3 | Sat Jan 24 00:00:00 1970 PST 124 | 4 | 00124 | Sun Jan 25 00:00:00 1970 PST 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST 127 | 407 | 00127_update7 | Wed Jan 28 00:00:00 1970 PST 128 | 8 | 00128 | Thu Jan 29 00:00:00 1970 PST 129 | 509 | 00129_update9 | Fri Jan 30 00:00:00 1970 PST 130 | 0 | 00130 | Sat Jan 31 00:00:00 1970 PST 131 | 1 | 00131 | Sun Feb 01 00:00:00 1970 PST 133 | 303 | 00133_update3 | Tue Feb 03 00:00:00 1970 PST 134 | 4 | 00134 | Wed Feb 04 00:00:00 1970 PST 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST 137 | 407 | 00137_update7 | Sat Feb 07 00:00:00 1970 PST 138 | 8 | 00138 | Sun Feb 08 00:00:00 1970 PST 139 | 509 | 00139_update9 | Mon Feb 09 00:00:00 1970 PST 140 | 0 | 00140 | Tue Feb 10 00:00:00 1970 PST 141 | 1 | 00141 | Wed Feb 11 00:00:00 1970 PST 143 | 303 | 00143_update3 | Fri Feb 13 00:00:00 1970 PST 144 | 4 | 00144 | Sat Feb 14 00:00:00 1970 PST 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST 147 | 407 | 00147_update7 | Tue Feb 17 00:00:00 1970 PST 148 | 8 | 00148 | Wed Feb 18 00:00:00 1970 PST 149 | 509 | 00149_update9 | Thu Feb 19 00:00:00 1970 PST 150 | 0 | 00150 | Fri Feb 20 00:00:00 1970 PST 151 | 1 | 00151 | Sat Feb 21 00:00:00 1970 PST 153 | 303 | 00153_update3 | Mon Feb 23 00:00:00 1970 PST 154 | 4 | 00154 | Tue Feb 24 00:00:00 1970 PST 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST 157 | 407 | 00157_update7 | Fri Feb 27 00:00:00 1970 PST 158 | 8 | 00158 | Sat Feb 28 00:00:00 1970 PST 159 | 509 | 00159_update9 | Sun Mar 01 00:00:00 1970 PST 160 | 0 | 00160 | Mon Mar 02 00:00:00 1970 PST 161 | 1 | 00161 | Tue Mar 03 00:00:00 1970 PST 163 | 303 | 00163_update3 | Thu Mar 05 00:00:00 1970 PST 164 | 4 | 00164 | Fri Mar 06 00:00:00 1970 PST 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST 167 | 407 | 00167_update7 | Mon Mar 09 00:00:00 1970 PST 168 | 8 | 00168 | Tue Mar 10 00:00:00 1970 PST 169 | 509 | 00169_update9 | Wed Mar 11 00:00:00 1970 PST 170 | 0 | 00170 | Thu Mar 12 00:00:00 1970 PST 171 | 1 | 00171 | Fri Mar 13 00:00:00 1970 PST 173 | 303 | 00173_update3 | Sun Mar 15 00:00:00 1970 PST 174 | 4 | 00174 | Mon Mar 16 00:00:00 1970 PST 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST 177 | 407 | 00177_update7 | Thu Mar 19 00:00:00 1970 PST 178 | 8 | 00178 | Fri Mar 20 00:00:00 1970 PST 179 | 509 | 00179_update9 | Sat Mar 21 00:00:00 1970 PST 180 | 0 | 00180 | Sun Mar 22 00:00:00 1970 PST 181 | 1 | 00181 | Mon Mar 23 00:00:00 1970 PST 183 | 303 | 00183_update3 | Wed Mar 25 00:00:00 1970 PST 184 | 4 | 00184 | Thu Mar 26 00:00:00 1970 PST 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST 187 | 407 | 00187_update7 | Sun Mar 29 00:00:00 1970 PST 188 | 8 | 00188 | Mon Mar 30 00:00:00 1970 PST 189 | 509 | 00189_update9 | Tue Mar 31 00:00:00 1970 PST 190 | 0 | 00190 | Wed Apr 01 00:00:00 1970 PST 191 | 1 | 00191 | Thu Apr 02 00:00:00 1970 PST 193 | 303 | 00193_update3 | Sat Apr 04 00:00:00 1970 PST 194 | 4 | 00194 | Sun Apr 05 00:00:00 1970 PST 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST 197 | 407 | 00197_update7 | Wed Apr 08 00:00:00 1970 PST 198 | 8 | 00198 | Thu Apr 09 00:00:00 1970 PST 199 | 509 | 00199_update9 | Fri Apr 10 00:00:00 1970 PST 200 | 0 | 00200 | Thu Jan 01 00:00:00 1970 PST 201 | 1 | 00201 | Fri Jan 02 00:00:00 1970 PST 203 | 303 | 00203_update3 | Sun Jan 04 00:00:00 1970 PST 204 | 4 | 00204 | Mon Jan 05 00:00:00 1970 PST 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST 207 | 407 | 00207_update7 | Thu Jan 08 00:00:00 1970 PST 208 | 8 | 00208 | Fri Jan 09 00:00:00 1970 PST 209 | 509 | 00209_update9 | Sat Jan 10 00:00:00 1970 PST 210 | 0 | 00210 | Sun Jan 11 00:00:00 1970 PST 211 | 1 | 00211 | Mon Jan 12 00:00:00 1970 PST 213 | 303 | 00213_update3 | Wed Jan 14 00:00:00 1970 PST 214 | 4 | 00214 | Thu Jan 15 00:00:00 1970 PST 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST 217 | 407 | 00217_update7 | Sun Jan 18 00:00:00 1970 PST 218 | 8 | 00218 | Mon Jan 19 00:00:00 1970 PST 219 | 509 | 00219_update9 | Tue Jan 20 00:00:00 1970 PST 220 | 0 | 00220 | Wed Jan 21 00:00:00 1970 PST 221 | 1 | 00221 | Thu Jan 22 00:00:00 1970 PST 223 | 303 | 00223_update3 | Sat Jan 24 00:00:00 1970 PST 224 | 4 | 00224 | Sun Jan 25 00:00:00 1970 PST 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST 227 | 407 | 00227_update7 | Wed Jan 28 00:00:00 1970 PST 228 | 8 | 00228 | Thu Jan 29 00:00:00 1970 PST 229 | 509 | 00229_update9 | Fri Jan 30 00:00:00 1970 PST 230 | 0 | 00230 | Sat Jan 31 00:00:00 1970 PST 231 | 1 | 00231 | Sun Feb 01 00:00:00 1970 PST 233 | 303 | 00233_update3 | Tue Feb 03 00:00:00 1970 PST 234 | 4 | 00234 | Wed Feb 04 00:00:00 1970 PST 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST 237 | 407 | 00237_update7 | Sat Feb 07 00:00:00 1970 PST 238 | 8 | 00238 | Sun Feb 08 00:00:00 1970 PST 239 | 509 | 00239_update9 | Mon Feb 09 00:00:00 1970 PST 240 | 0 | 00240 | Tue Feb 10 00:00:00 1970 PST 241 | 1 | 00241 | Wed Feb 11 00:00:00 1970 PST 243 | 303 | 00243_update3 | Fri Feb 13 00:00:00 1970 PST 244 | 4 | 00244 | Sat Feb 14 00:00:00 1970 PST 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST 247 | 407 | 00247_update7 | Tue Feb 17 00:00:00 1970 PST 248 | 8 | 00248 | Wed Feb 18 00:00:00 1970 PST 249 | 509 | 00249_update9 | Thu Feb 19 00:00:00 1970 PST 250 | 0 | 00250 | Fri Feb 20 00:00:00 1970 PST 251 | 1 | 00251 | Sat Feb 21 00:00:00 1970 PST 253 | 303 | 00253_update3 | Mon Feb 23 00:00:00 1970 PST 254 | 4 | 00254 | Tue Feb 24 00:00:00 1970 PST 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST 257 | 407 | 00257_update7 | Fri Feb 27 00:00:00 1970 PST 258 | 8 | 00258 | Sat Feb 28 00:00:00 1970 PST 259 | 509 | 00259_update9 | Sun Mar 01 00:00:00 1970 PST 260 | 0 | 00260 | Mon Mar 02 00:00:00 1970 PST 261 | 1 | 00261 | Tue Mar 03 00:00:00 1970 PST 263 | 303 | 00263_update3 | Thu Mar 05 00:00:00 1970 PST 264 | 4 | 00264 | Fri Mar 06 00:00:00 1970 PST 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST 267 | 407 | 00267_update7 | Mon Mar 09 00:00:00 1970 PST 268 | 8 | 00268 | Tue Mar 10 00:00:00 1970 PST 269 | 509 | 00269_update9 | Wed Mar 11 00:00:00 1970 PST 270 | 0 | 00270 | Thu Mar 12 00:00:00 1970 PST 271 | 1 | 00271 | Fri Mar 13 00:00:00 1970 PST 273 | 303 | 00273_update3 | Sun Mar 15 00:00:00 1970 PST 274 | 4 | 00274 | Mon Mar 16 00:00:00 1970 PST 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST 277 | 407 | 00277_update7 | Thu Mar 19 00:00:00 1970 PST 278 | 8 | 00278 | Fri Mar 20 00:00:00 1970 PST 279 | 509 | 00279_update9 | Sat Mar 21 00:00:00 1970 PST 280 | 0 | 00280 | Sun Mar 22 00:00:00 1970 PST 281 | 1 | 00281 | Mon Mar 23 00:00:00 1970 PST 283 | 303 | 00283_update3 | Wed Mar 25 00:00:00 1970 PST 284 | 4 | 00284 | Thu Mar 26 00:00:00 1970 PST 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST 287 | 407 | 00287_update7 | Sun Mar 29 00:00:00 1970 PST 288 | 8 | 00288 | Mon Mar 30 00:00:00 1970 PST 289 | 509 | 00289_update9 | Tue Mar 31 00:00:00 1970 PST 290 | 0 | 00290 | Wed Apr 01 00:00:00 1970 PST 291 | 1 | 00291 | Thu Apr 02 00:00:00 1970 PST 293 | 303 | 00293_update3 | Sat Apr 04 00:00:00 1970 PST 294 | 4 | 00294 | Sun Apr 05 00:00:00 1970 PST 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST 297 | 407 | 00297_update7 | Wed Apr 08 00:00:00 1970 PST 298 | 8 | 00298 | Thu Apr 09 00:00:00 1970 PST 299 | 509 | 00299_update9 | Fri Apr 10 00:00:00 1970 PST 300 | 0 | 00300 | Thu Jan 01 00:00:00 1970 PST 301 | 1 | 00301 | Fri Jan 02 00:00:00 1970 PST 303 | 303 | 00303_update3 | Sun Jan 04 00:00:00 1970 PST 304 | 4 | 00304 | Mon Jan 05 00:00:00 1970 PST 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST 307 | 407 | 00307_update7 | Thu Jan 08 00:00:00 1970 PST 308 | 8 | 00308 | Fri Jan 09 00:00:00 1970 PST 309 | 509 | 00309_update9 | Sat Jan 10 00:00:00 1970 PST 310 | 0 | 00310 | Sun Jan 11 00:00:00 1970 PST 311 | 1 | 00311 | Mon Jan 12 00:00:00 1970 PST 313 | 303 | 00313_update3 | Wed Jan 14 00:00:00 1970 PST 314 | 4 | 00314 | Thu Jan 15 00:00:00 1970 PST 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST 317 | 407 | 00317_update7 | Sun Jan 18 00:00:00 1970 PST 318 | 8 | 00318 | Mon Jan 19 00:00:00 1970 PST 319 | 509 | 00319_update9 | Tue Jan 20 00:00:00 1970 PST 320 | 0 | 00320 | Wed Jan 21 00:00:00 1970 PST 321 | 1 | 00321 | Thu Jan 22 00:00:00 1970 PST 323 | 303 | 00323_update3 | Sat Jan 24 00:00:00 1970 PST 324 | 4 | 00324 | Sun Jan 25 00:00:00 1970 PST 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST 327 | 407 | 00327_update7 | Wed Jan 28 00:00:00 1970 PST 328 | 8 | 00328 | Thu Jan 29 00:00:00 1970 PST 329 | 509 | 00329_update9 | Fri Jan 30 00:00:00 1970 PST 330 | 0 | 00330 | Sat Jan 31 00:00:00 1970 PST 331 | 1 | 00331 | Sun Feb 01 00:00:00 1970 PST 333 | 303 | 00333_update3 | Tue Feb 03 00:00:00 1970 PST 334 | 4 | 00334 | Wed Feb 04 00:00:00 1970 PST 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST 337 | 407 | 00337_update7 | Sat Feb 07 00:00:00 1970 PST 338 | 8 | 00338 | Sun Feb 08 00:00:00 1970 PST 339 | 509 | 00339_update9 | Mon Feb 09 00:00:00 1970 PST 340 | 0 | 00340 | Tue Feb 10 00:00:00 1970 PST 341 | 1 | 00341 | Wed Feb 11 00:00:00 1970 PST 343 | 303 | 00343_update3 | Fri Feb 13 00:00:00 1970 PST 344 | 4 | 00344 | Sat Feb 14 00:00:00 1970 PST 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST 347 | 407 | 00347_update7 | Tue Feb 17 00:00:00 1970 PST 348 | 8 | 00348 | Wed Feb 18 00:00:00 1970 PST 349 | 509 | 00349_update9 | Thu Feb 19 00:00:00 1970 PST 350 | 0 | 00350 | Fri Feb 20 00:00:00 1970 PST 351 | 1 | 00351 | Sat Feb 21 00:00:00 1970 PST 353 | 303 | 00353_update3 | Mon Feb 23 00:00:00 1970 PST 354 | 4 | 00354 | Tue Feb 24 00:00:00 1970 PST 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST 357 | 407 | 00357_update7 | Fri Feb 27 00:00:00 1970 PST 358 | 8 | 00358 | Sat Feb 28 00:00:00 1970 PST 359 | 509 | 00359_update9 | Sun Mar 01 00:00:00 1970 PST 360 | 0 | 00360 | Mon Mar 02 00:00:00 1970 PST 361 | 1 | 00361 | Tue Mar 03 00:00:00 1970 PST 363 | 303 | 00363_update3 | Thu Mar 05 00:00:00 1970 PST 364 | 4 | 00364 | Fri Mar 06 00:00:00 1970 PST 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST 367 | 407 | 00367_update7 | Mon Mar 09 00:00:00 1970 PST 368 | 8 | 00368 | Tue Mar 10 00:00:00 1970 PST 369 | 509 | 00369_update9 | Wed Mar 11 00:00:00 1970 PST 370 | 0 | 00370 | Thu Mar 12 00:00:00 1970 PST 371 | 1 | 00371 | Fri Mar 13 00:00:00 1970 PST 373 | 303 | 00373_update3 | Sun Mar 15 00:00:00 1970 PST 374 | 4 | 00374 | Mon Mar 16 00:00:00 1970 PST 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST 377 | 407 | 00377_update7 | Thu Mar 19 00:00:00 1970 PST 378 | 8 | 00378 | Fri Mar 20 00:00:00 1970 PST 379 | 509 | 00379_update9 | Sat Mar 21 00:00:00 1970 PST 380 | 0 | 00380 | Sun Mar 22 00:00:00 1970 PST 381 | 1 | 00381 | Mon Mar 23 00:00:00 1970 PST 383 | 303 | 00383_update3 | Wed Mar 25 00:00:00 1970 PST 384 | 4 | 00384 | Thu Mar 26 00:00:00 1970 PST 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST 387 | 407 | 00387_update7 | Sun Mar 29 00:00:00 1970 PST 388 | 8 | 00388 | Mon Mar 30 00:00:00 1970 PST 389 | 509 | 00389_update9 | Tue Mar 31 00:00:00 1970 PST 390 | 0 | 00390 | Wed Apr 01 00:00:00 1970 PST 391 | 1 | 00391 | Thu Apr 02 00:00:00 1970 PST 393 | 303 | 00393_update3 | Sat Apr 04 00:00:00 1970 PST 394 | 4 | 00394 | Sun Apr 05 00:00:00 1970 PST 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST 397 | 407 | 00397_update7 | Wed Apr 08 00:00:00 1970 PST 398 | 8 | 00398 | Thu Apr 09 00:00:00 1970 PST 399 | 509 | 00399_update9 | Fri Apr 10 00:00:00 1970 PST 400 | 0 | 00400 | Thu Jan 01 00:00:00 1970 PST 401 | 1 | 00401 | Fri Jan 02 00:00:00 1970 PST 403 | 303 | 00403_update3 | Sun Jan 04 00:00:00 1970 PST 404 | 4 | 00404 | Mon Jan 05 00:00:00 1970 PST 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST 407 | 407 | 00407_update7 | Thu Jan 08 00:00:00 1970 PST 408 | 8 | 00408 | Fri Jan 09 00:00:00 1970 PST 409 | 509 | 00409_update9 | Sat Jan 10 00:00:00 1970 PST 410 | 0 | 00410 | Sun Jan 11 00:00:00 1970 PST 411 | 1 | 00411 | Mon Jan 12 00:00:00 1970 PST 413 | 303 | 00413_update3 | Wed Jan 14 00:00:00 1970 PST 414 | 4 | 00414 | Thu Jan 15 00:00:00 1970 PST 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST 417 | 407 | 00417_update7 | Sun Jan 18 00:00:00 1970 PST 418 | 8 | 00418 | Mon Jan 19 00:00:00 1970 PST 419 | 509 | 00419_update9 | Tue Jan 20 00:00:00 1970 PST 420 | 0 | 00420 | Wed Jan 21 00:00:00 1970 PST 421 | 1 | 00421 | Thu Jan 22 00:00:00 1970 PST 423 | 303 | 00423_update3 | Sat Jan 24 00:00:00 1970 PST 424 | 4 | 00424 | Sun Jan 25 00:00:00 1970 PST 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST 427 | 407 | 00427_update7 | Wed Jan 28 00:00:00 1970 PST 428 | 8 | 00428 | Thu Jan 29 00:00:00 1970 PST 429 | 509 | 00429_update9 | Fri Jan 30 00:00:00 1970 PST 430 | 0 | 00430 | Sat Jan 31 00:00:00 1970 PST 431 | 1 | 00431 | Sun Feb 01 00:00:00 1970 PST 433 | 303 | 00433_update3 | Tue Feb 03 00:00:00 1970 PST 434 | 4 | 00434 | Wed Feb 04 00:00:00 1970 PST 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST 437 | 407 | 00437_update7 | Sat Feb 07 00:00:00 1970 PST 438 | 8 | 00438 | Sun Feb 08 00:00:00 1970 PST 439 | 509 | 00439_update9 | Mon Feb 09 00:00:00 1970 PST 440 | 0 | 00440 | Tue Feb 10 00:00:00 1970 PST 441 | 1 | 00441 | Wed Feb 11 00:00:00 1970 PST 443 | 303 | 00443_update3 | Fri Feb 13 00:00:00 1970 PST 444 | 4 | 00444 | Sat Feb 14 00:00:00 1970 PST 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST 447 | 407 | 00447_update7 | Tue Feb 17 00:00:00 1970 PST 448 | 8 | 00448 | Wed Feb 18 00:00:00 1970 PST 449 | 509 | 00449_update9 | Thu Feb 19 00:00:00 1970 PST 450 | 0 | 00450 | Fri Feb 20 00:00:00 1970 PST 451 | 1 | 00451 | Sat Feb 21 00:00:00 1970 PST 453 | 303 | 00453_update3 | Mon Feb 23 00:00:00 1970 PST 454 | 4 | 00454 | Tue Feb 24 00:00:00 1970 PST 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST 457 | 407 | 00457_update7 | Fri Feb 27 00:00:00 1970 PST 458 | 8 | 00458 | Sat Feb 28 00:00:00 1970 PST 459 | 509 | 00459_update9 | Sun Mar 01 00:00:00 1970 PST 460 | 0 | 00460 | Mon Mar 02 00:00:00 1970 PST 461 | 1 | 00461 | Tue Mar 03 00:00:00 1970 PST 463 | 303 | 00463_update3 | Thu Mar 05 00:00:00 1970 PST 464 | 4 | 00464 | Fri Mar 06 00:00:00 1970 PST 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST 467 | 407 | 00467_update7 | Mon Mar 09 00:00:00 1970 PST 468 | 8 | 00468 | Tue Mar 10 00:00:00 1970 PST 469 | 509 | 00469_update9 | Wed Mar 11 00:00:00 1970 PST 470 | 0 | 00470 | Thu Mar 12 00:00:00 1970 PST 471 | 1 | 00471 | Fri Mar 13 00:00:00 1970 PST 473 | 303 | 00473_update3 | Sun Mar 15 00:00:00 1970 PST 474 | 4 | 00474 | Mon Mar 16 00:00:00 1970 PST 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST 477 | 407 | 00477_update7 | Thu Mar 19 00:00:00 1970 PST 478 | 8 | 00478 | Fri Mar 20 00:00:00 1970 PST 479 | 509 | 00479_update9 | Sat Mar 21 00:00:00 1970 PST 480 | 0 | 00480 | Sun Mar 22 00:00:00 1970 PST 481 | 1 | 00481 | Mon Mar 23 00:00:00 1970 PST 483 | 303 | 00483_update3 | Wed Mar 25 00:00:00 1970 PST 484 | 4 | 00484 | Thu Mar 26 00:00:00 1970 PST 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST 487 | 407 | 00487_update7 | Sun Mar 29 00:00:00 1970 PST 488 | 8 | 00488 | Mon Mar 30 00:00:00 1970 PST 489 | 509 | 00489_update9 | Tue Mar 31 00:00:00 1970 PST 490 | 0 | 00490 | Wed Apr 01 00:00:00 1970 PST 491 | 1 | 00491 | Thu Apr 02 00:00:00 1970 PST 493 | 303 | 00493_update3 | Sat Apr 04 00:00:00 1970 PST 494 | 4 | 00494 | Sun Apr 05 00:00:00 1970 PST 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST 497 | 407 | 00497_update7 | Wed Apr 08 00:00:00 1970 PST 498 | 8 | 00498 | Thu Apr 09 00:00:00 1970 PST 499 | 509 | 00499_update9 | Fri Apr 10 00:00:00 1970 PST 500 | 0 | 00500 | Thu Jan 01 00:00:00 1970 PST 501 | 1 | 00501 | Fri Jan 02 00:00:00 1970 PST 503 | 303 | 00503_update3 | Sun Jan 04 00:00:00 1970 PST 504 | 4 | 00504 | Mon Jan 05 00:00:00 1970 PST 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST 507 | 407 | 00507_update7 | Thu Jan 08 00:00:00 1970 PST 508 | 8 | 00508 | Fri Jan 09 00:00:00 1970 PST 509 | 509 | 00509_update9 | Sat Jan 10 00:00:00 1970 PST 510 | 0 | 00510 | Sun Jan 11 00:00:00 1970 PST 511 | 1 | 00511 | Mon Jan 12 00:00:00 1970 PST 513 | 303 | 00513_update3 | Wed Jan 14 00:00:00 1970 PST 514 | 4 | 00514 | Thu Jan 15 00:00:00 1970 PST 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST 517 | 407 | 00517_update7 | Sun Jan 18 00:00:00 1970 PST 518 | 8 | 00518 | Mon Jan 19 00:00:00 1970 PST 519 | 509 | 00519_update9 | Tue Jan 20 00:00:00 1970 PST 520 | 0 | 00520 | Wed Jan 21 00:00:00 1970 PST 521 | 1 | 00521 | Thu Jan 22 00:00:00 1970 PST 523 | 303 | 00523_update3 | Sat Jan 24 00:00:00 1970 PST 524 | 4 | 00524 | Sun Jan 25 00:00:00 1970 PST 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST 527 | 407 | 00527_update7 | Wed Jan 28 00:00:00 1970 PST 528 | 8 | 00528 | Thu Jan 29 00:00:00 1970 PST 529 | 509 | 00529_update9 | Fri Jan 30 00:00:00 1970 PST 530 | 0 | 00530 | Sat Jan 31 00:00:00 1970 PST 531 | 1 | 00531 | Sun Feb 01 00:00:00 1970 PST 533 | 303 | 00533_update3 | Tue Feb 03 00:00:00 1970 PST 534 | 4 | 00534 | Wed Feb 04 00:00:00 1970 PST 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST 537 | 407 | 00537_update7 | Sat Feb 07 00:00:00 1970 PST 538 | 8 | 00538 | Sun Feb 08 00:00:00 1970 PST 539 | 509 | 00539_update9 | Mon Feb 09 00:00:00 1970 PST 540 | 0 | 00540 | Tue Feb 10 00:00:00 1970 PST 541 | 1 | 00541 | Wed Feb 11 00:00:00 1970 PST 543 | 303 | 00543_update3 | Fri Feb 13 00:00:00 1970 PST 544 | 4 | 00544 | Sat Feb 14 00:00:00 1970 PST 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST 547 | 407 | 00547_update7 | Tue Feb 17 00:00:00 1970 PST 548 | 8 | 00548 | Wed Feb 18 00:00:00 1970 PST 549 | 509 | 00549_update9 | Thu Feb 19 00:00:00 1970 PST 550 | 0 | 00550 | Fri Feb 20 00:00:00 1970 PST 551 | 1 | 00551 | Sat Feb 21 00:00:00 1970 PST 553 | 303 | 00553_update3 | Mon Feb 23 00:00:00 1970 PST 554 | 4 | 00554 | Tue Feb 24 00:00:00 1970 PST 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST 557 | 407 | 00557_update7 | Fri Feb 27 00:00:00 1970 PST 558 | 8 | 00558 | Sat Feb 28 00:00:00 1970 PST 559 | 509 | 00559_update9 | Sun Mar 01 00:00:00 1970 PST 560 | 0 | 00560 | Mon Mar 02 00:00:00 1970 PST 561 | 1 | 00561 | Tue Mar 03 00:00:00 1970 PST 563 | 303 | 00563_update3 | Thu Mar 05 00:00:00 1970 PST 564 | 4 | 00564 | Fri Mar 06 00:00:00 1970 PST 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST 567 | 407 | 00567_update7 | Mon Mar 09 00:00:00 1970 PST 568 | 8 | 00568 | Tue Mar 10 00:00:00 1970 PST 569 | 509 | 00569_update9 | Wed Mar 11 00:00:00 1970 PST 570 | 0 | 00570 | Thu Mar 12 00:00:00 1970 PST 571 | 1 | 00571 | Fri Mar 13 00:00:00 1970 PST 573 | 303 | 00573_update3 | Sun Mar 15 00:00:00 1970 PST 574 | 4 | 00574 | Mon Mar 16 00:00:00 1970 PST 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST 577 | 407 | 00577_update7 | Thu Mar 19 00:00:00 1970 PST 578 | 8 | 00578 | Fri Mar 20 00:00:00 1970 PST 579 | 509 | 00579_update9 | Sat Mar 21 00:00:00 1970 PST 580 | 0 | 00580 | Sun Mar 22 00:00:00 1970 PST 581 | 1 | 00581 | Mon Mar 23 00:00:00 1970 PST 583 | 303 | 00583_update3 | Wed Mar 25 00:00:00 1970 PST 584 | 4 | 00584 | Thu Mar 26 00:00:00 1970 PST 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST 587 | 407 | 00587_update7 | Sun Mar 29 00:00:00 1970 PST 588 | 8 | 00588 | Mon Mar 30 00:00:00 1970 PST 589 | 509 | 00589_update9 | Tue Mar 31 00:00:00 1970 PST 590 | 0 | 00590 | Wed Apr 01 00:00:00 1970 PST 591 | 1 | 00591 | Thu Apr 02 00:00:00 1970 PST 593 | 303 | 00593_update3 | Sat Apr 04 00:00:00 1970 PST 594 | 4 | 00594 | Sun Apr 05 00:00:00 1970 PST 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST 597 | 407 | 00597_update7 | Wed Apr 08 00:00:00 1970 PST 598 | 8 | 00598 | Thu Apr 09 00:00:00 1970 PST 599 | 509 | 00599_update9 | Fri Apr 10 00:00:00 1970 PST 600 | 0 | 00600 | Thu Jan 01 00:00:00 1970 PST 601 | 1 | 00601 | Fri Jan 02 00:00:00 1970 PST 603 | 303 | 00603_update3 | Sun Jan 04 00:00:00 1970 PST 604 | 4 | 00604 | Mon Jan 05 00:00:00 1970 PST 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST 607 | 407 | 00607_update7 | Thu Jan 08 00:00:00 1970 PST 608 | 8 | 00608 | Fri Jan 09 00:00:00 1970 PST 609 | 509 | 00609_update9 | Sat Jan 10 00:00:00 1970 PST 610 | 0 | 00610 | Sun Jan 11 00:00:00 1970 PST 611 | 1 | 00611 | Mon Jan 12 00:00:00 1970 PST 613 | 303 | 00613_update3 | Wed Jan 14 00:00:00 1970 PST 614 | 4 | 00614 | Thu Jan 15 00:00:00 1970 PST 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST 617 | 407 | 00617_update7 | Sun Jan 18 00:00:00 1970 PST 618 | 8 | 00618 | Mon Jan 19 00:00:00 1970 PST 619 | 509 | 00619_update9 | Tue Jan 20 00:00:00 1970 PST 620 | 0 | 00620 | Wed Jan 21 00:00:00 1970 PST 621 | 1 | 00621 | Thu Jan 22 00:00:00 1970 PST 623 | 303 | 00623_update3 | Sat Jan 24 00:00:00 1970 PST 624 | 4 | 00624 | Sun Jan 25 00:00:00 1970 PST 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST 627 | 407 | 00627_update7 | Wed Jan 28 00:00:00 1970 PST 628 | 8 | 00628 | Thu Jan 29 00:00:00 1970 PST 629 | 509 | 00629_update9 | Fri Jan 30 00:00:00 1970 PST 630 | 0 | 00630 | Sat Jan 31 00:00:00 1970 PST 631 | 1 | 00631 | Sun Feb 01 00:00:00 1970 PST 633 | 303 | 00633_update3 | Tue Feb 03 00:00:00 1970 PST 634 | 4 | 00634 | Wed Feb 04 00:00:00 1970 PST 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST 637 | 407 | 00637_update7 | Sat Feb 07 00:00:00 1970 PST 638 | 8 | 00638 | Sun Feb 08 00:00:00 1970 PST 639 | 509 | 00639_update9 | Mon Feb 09 00:00:00 1970 PST 640 | 0 | 00640 | Tue Feb 10 00:00:00 1970 PST 641 | 1 | 00641 | Wed Feb 11 00:00:00 1970 PST 643 | 303 | 00643_update3 | Fri Feb 13 00:00:00 1970 PST 644 | 4 | 00644 | Sat Feb 14 00:00:00 1970 PST 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST 647 | 407 | 00647_update7 | Tue Feb 17 00:00:00 1970 PST 648 | 8 | 00648 | Wed Feb 18 00:00:00 1970 PST 649 | 509 | 00649_update9 | Thu Feb 19 00:00:00 1970 PST 650 | 0 | 00650 | Fri Feb 20 00:00:00 1970 PST 651 | 1 | 00651 | Sat Feb 21 00:00:00 1970 PST 653 | 303 | 00653_update3 | Mon Feb 23 00:00:00 1970 PST 654 | 4 | 00654 | Tue Feb 24 00:00:00 1970 PST 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST 657 | 407 | 00657_update7 | Fri Feb 27 00:00:00 1970 PST 658 | 8 | 00658 | Sat Feb 28 00:00:00 1970 PST 659 | 509 | 00659_update9 | Sun Mar 01 00:00:00 1970 PST 660 | 0 | 00660 | Mon Mar 02 00:00:00 1970 PST 661 | 1 | 00661 | Tue Mar 03 00:00:00 1970 PST 663 | 303 | 00663_update3 | Thu Mar 05 00:00:00 1970 PST 664 | 4 | 00664 | Fri Mar 06 00:00:00 1970 PST 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST 667 | 407 | 00667_update7 | Mon Mar 09 00:00:00 1970 PST 668 | 8 | 00668 | Tue Mar 10 00:00:00 1970 PST 669 | 509 | 00669_update9 | Wed Mar 11 00:00:00 1970 PST 670 | 0 | 00670 | Thu Mar 12 00:00:00 1970 PST 671 | 1 | 00671 | Fri Mar 13 00:00:00 1970 PST 673 | 303 | 00673_update3 | Sun Mar 15 00:00:00 1970 PST 674 | 4 | 00674 | Mon Mar 16 00:00:00 1970 PST 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST 677 | 407 | 00677_update7 | Thu Mar 19 00:00:00 1970 PST 678 | 8 | 00678 | Fri Mar 20 00:00:00 1970 PST 679 | 509 | 00679_update9 | Sat Mar 21 00:00:00 1970 PST 680 | 0 | 00680 | Sun Mar 22 00:00:00 1970 PST 681 | 1 | 00681 | Mon Mar 23 00:00:00 1970 PST 683 | 303 | 00683_update3 | Wed Mar 25 00:00:00 1970 PST 684 | 4 | 00684 | Thu Mar 26 00:00:00 1970 PST 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST 687 | 407 | 00687_update7 | Sun Mar 29 00:00:00 1970 PST 688 | 8 | 00688 | Mon Mar 30 00:00:00 1970 PST 689 | 509 | 00689_update9 | Tue Mar 31 00:00:00 1970 PST 690 | 0 | 00690 | Wed Apr 01 00:00:00 1970 PST 691 | 1 | 00691 | Thu Apr 02 00:00:00 1970 PST 693 | 303 | 00693_update3 | Sat Apr 04 00:00:00 1970 PST 694 | 4 | 00694 | Sun Apr 05 00:00:00 1970 PST 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST 697 | 407 | 00697_update7 | Wed Apr 08 00:00:00 1970 PST 698 | 8 | 00698 | Thu Apr 09 00:00:00 1970 PST 699 | 509 | 00699_update9 | Fri Apr 10 00:00:00 1970 PST 700 | 0 | 00700 | Thu Jan 01 00:00:00 1970 PST 701 | 1 | 00701 | Fri Jan 02 00:00:00 1970 PST 703 | 303 | 00703_update3 | Sun Jan 04 00:00:00 1970 PST 704 | 4 | 00704 | Mon Jan 05 00:00:00 1970 PST 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST 707 | 407 | 00707_update7 | Thu Jan 08 00:00:00 1970 PST 708 | 8 | 00708 | Fri Jan 09 00:00:00 1970 PST 709 | 509 | 00709_update9 | Sat Jan 10 00:00:00 1970 PST 710 | 0 | 00710 | Sun Jan 11 00:00:00 1970 PST 711 | 1 | 00711 | Mon Jan 12 00:00:00 1970 PST 713 | 303 | 00713_update3 | Wed Jan 14 00:00:00 1970 PST 714 | 4 | 00714 | Thu Jan 15 00:00:00 1970 PST 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST 717 | 407 | 00717_update7 | Sun Jan 18 00:00:00 1970 PST 718 | 8 | 00718 | Mon Jan 19 00:00:00 1970 PST 719 | 509 | 00719_update9 | Tue Jan 20 00:00:00 1970 PST 720 | 0 | 00720 | Wed Jan 21 00:00:00 1970 PST 721 | 1 | 00721 | Thu Jan 22 00:00:00 1970 PST 723 | 303 | 00723_update3 | Sat Jan 24 00:00:00 1970 PST 724 | 4 | 00724 | Sun Jan 25 00:00:00 1970 PST 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST 727 | 407 | 00727_update7 | Wed Jan 28 00:00:00 1970 PST 728 | 8 | 00728 | Thu Jan 29 00:00:00 1970 PST 729 | 509 | 00729_update9 | Fri Jan 30 00:00:00 1970 PST 730 | 0 | 00730 | Sat Jan 31 00:00:00 1970 PST 731 | 1 | 00731 | Sun Feb 01 00:00:00 1970 PST 733 | 303 | 00733_update3 | Tue Feb 03 00:00:00 1970 PST 734 | 4 | 00734 | Wed Feb 04 00:00:00 1970 PST 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST 737 | 407 | 00737_update7 | Sat Feb 07 00:00:00 1970 PST 738 | 8 | 00738 | Sun Feb 08 00:00:00 1970 PST 739 | 509 | 00739_update9 | Mon Feb 09 00:00:00 1970 PST 740 | 0 | 00740 | Tue Feb 10 00:00:00 1970 PST 741 | 1 | 00741 | Wed Feb 11 00:00:00 1970 PST 743 | 303 | 00743_update3 | Fri Feb 13 00:00:00 1970 PST 744 | 4 | 00744 | Sat Feb 14 00:00:00 1970 PST 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST 747 | 407 | 00747_update7 | Tue Feb 17 00:00:00 1970 PST 748 | 8 | 00748 | Wed Feb 18 00:00:00 1970 PST 749 | 509 | 00749_update9 | Thu Feb 19 00:00:00 1970 PST 750 | 0 | 00750 | Fri Feb 20 00:00:00 1970 PST 751 | 1 | 00751 | Sat Feb 21 00:00:00 1970 PST 753 | 303 | 00753_update3 | Mon Feb 23 00:00:00 1970 PST 754 | 4 | 00754 | Tue Feb 24 00:00:00 1970 PST 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST 757 | 407 | 00757_update7 | Fri Feb 27 00:00:00 1970 PST 758 | 8 | 00758 | Sat Feb 28 00:00:00 1970 PST 759 | 509 | 00759_update9 | Sun Mar 01 00:00:00 1970 PST 760 | 0 | 00760 | Mon Mar 02 00:00:00 1970 PST 761 | 1 | 00761 | Tue Mar 03 00:00:00 1970 PST 763 | 303 | 00763_update3 | Thu Mar 05 00:00:00 1970 PST 764 | 4 | 00764 | Fri Mar 06 00:00:00 1970 PST 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST 767 | 407 | 00767_update7 | Mon Mar 09 00:00:00 1970 PST 768 | 8 | 00768 | Tue Mar 10 00:00:00 1970 PST 769 | 509 | 00769_update9 | Wed Mar 11 00:00:00 1970 PST 770 | 0 | 00770 | Thu Mar 12 00:00:00 1970 PST 771 | 1 | 00771 | Fri Mar 13 00:00:00 1970 PST 773 | 303 | 00773_update3 | Sun Mar 15 00:00:00 1970 PST 774 | 4 | 00774 | Mon Mar 16 00:00:00 1970 PST 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST 777 | 407 | 00777_update7 | Thu Mar 19 00:00:00 1970 PST 778 | 8 | 00778 | Fri Mar 20 00:00:00 1970 PST 779 | 509 | 00779_update9 | Sat Mar 21 00:00:00 1970 PST 780 | 0 | 00780 | Sun Mar 22 00:00:00 1970 PST 781 | 1 | 00781 | Mon Mar 23 00:00:00 1970 PST 783 | 303 | 00783_update3 | Wed Mar 25 00:00:00 1970 PST 784 | 4 | 00784 | Thu Mar 26 00:00:00 1970 PST 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST 787 | 407 | 00787_update7 | Sun Mar 29 00:00:00 1970 PST 788 | 8 | 00788 | Mon Mar 30 00:00:00 1970 PST 789 | 509 | 00789_update9 | Tue Mar 31 00:00:00 1970 PST 790 | 0 | 00790 | Wed Apr 01 00:00:00 1970 PST 791 | 1 | 00791 | Thu Apr 02 00:00:00 1970 PST 793 | 303 | 00793_update3 | Sat Apr 04 00:00:00 1970 PST 794 | 4 | 00794 | Sun Apr 05 00:00:00 1970 PST 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST 797 | 407 | 00797_update7 | Wed Apr 08 00:00:00 1970 PST 798 | 8 | 00798 | Thu Apr 09 00:00:00 1970 PST 799 | 509 | 00799_update9 | Fri Apr 10 00:00:00 1970 PST 800 | 0 | 00800 | Thu Jan 01 00:00:00 1970 PST 801 | 1 | 00801 | Fri Jan 02 00:00:00 1970 PST 803 | 303 | 00803_update3 | Sun Jan 04 00:00:00 1970 PST 804 | 4 | 00804 | Mon Jan 05 00:00:00 1970 PST 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST 807 | 407 | 00807_update7 | Thu Jan 08 00:00:00 1970 PST 808 | 8 | 00808 | Fri Jan 09 00:00:00 1970 PST 809 | 509 | 00809_update9 | Sat Jan 10 00:00:00 1970 PST 810 | 0 | 00810 | Sun Jan 11 00:00:00 1970 PST 811 | 1 | 00811 | Mon Jan 12 00:00:00 1970 PST 813 | 303 | 00813_update3 | Wed Jan 14 00:00:00 1970 PST 814 | 4 | 00814 | Thu Jan 15 00:00:00 1970 PST 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST 817 | 407 | 00817_update7 | Sun Jan 18 00:00:00 1970 PST 818 | 8 | 00818 | Mon Jan 19 00:00:00 1970 PST 819 | 509 | 00819_update9 | Tue Jan 20 00:00:00 1970 PST 820 | 0 | 00820 | Wed Jan 21 00:00:00 1970 PST 821 | 1 | 00821 | Thu Jan 22 00:00:00 1970 PST 823 | 303 | 00823_update3 | Sat Jan 24 00:00:00 1970 PST 824 | 4 | 00824 | Sun Jan 25 00:00:00 1970 PST 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST 827 | 407 | 00827_update7 | Wed Jan 28 00:00:00 1970 PST 828 | 8 | 00828 | Thu Jan 29 00:00:00 1970 PST 829 | 509 | 00829_update9 | Fri Jan 30 00:00:00 1970 PST 830 | 0 | 00830 | Sat Jan 31 00:00:00 1970 PST 831 | 1 | 00831 | Sun Feb 01 00:00:00 1970 PST 833 | 303 | 00833_update3 | Tue Feb 03 00:00:00 1970 PST 834 | 4 | 00834 | Wed Feb 04 00:00:00 1970 PST 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST 837 | 407 | 00837_update7 | Sat Feb 07 00:00:00 1970 PST 838 | 8 | 00838 | Sun Feb 08 00:00:00 1970 PST 839 | 509 | 00839_update9 | Mon Feb 09 00:00:00 1970 PST 840 | 0 | 00840 | Tue Feb 10 00:00:00 1970 PST 841 | 1 | 00841 | Wed Feb 11 00:00:00 1970 PST 843 | 303 | 00843_update3 | Fri Feb 13 00:00:00 1970 PST 844 | 4 | 00844 | Sat Feb 14 00:00:00 1970 PST 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST 847 | 407 | 00847_update7 | Tue Feb 17 00:00:00 1970 PST 848 | 8 | 00848 | Wed Feb 18 00:00:00 1970 PST 849 | 509 | 00849_update9 | Thu Feb 19 00:00:00 1970 PST 850 | 0 | 00850 | Fri Feb 20 00:00:00 1970 PST 851 | 1 | 00851 | Sat Feb 21 00:00:00 1970 PST 853 | 303 | 00853_update3 | Mon Feb 23 00:00:00 1970 PST 854 | 4 | 00854 | Tue Feb 24 00:00:00 1970 PST 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST 857 | 407 | 00857_update7 | Fri Feb 27 00:00:00 1970 PST 858 | 8 | 00858 | Sat Feb 28 00:00:00 1970 PST 859 | 509 | 00859_update9 | Sun Mar 01 00:00:00 1970 PST 860 | 0 | 00860 | Mon Mar 02 00:00:00 1970 PST 861 | 1 | 00861 | Tue Mar 03 00:00:00 1970 PST 863 | 303 | 00863_update3 | Thu Mar 05 00:00:00 1970 PST 864 | 4 | 00864 | Fri Mar 06 00:00:00 1970 PST 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST 867 | 407 | 00867_update7 | Mon Mar 09 00:00:00 1970 PST 868 | 8 | 00868 | Tue Mar 10 00:00:00 1970 PST 869 | 509 | 00869_update9 | Wed Mar 11 00:00:00 1970 PST 870 | 0 | 00870 | Thu Mar 12 00:00:00 1970 PST 871 | 1 | 00871 | Fri Mar 13 00:00:00 1970 PST 873 | 303 | 00873_update3 | Sun Mar 15 00:00:00 1970 PST 874 | 4 | 00874 | Mon Mar 16 00:00:00 1970 PST 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST 877 | 407 | 00877_update7 | Thu Mar 19 00:00:00 1970 PST 878 | 8 | 00878 | Fri Mar 20 00:00:00 1970 PST 879 | 509 | 00879_update9 | Sat Mar 21 00:00:00 1970 PST 880 | 0 | 00880 | Sun Mar 22 00:00:00 1970 PST 881 | 1 | 00881 | Mon Mar 23 00:00:00 1970 PST 883 | 303 | 00883_update3 | Wed Mar 25 00:00:00 1970 PST 884 | 4 | 00884 | Thu Mar 26 00:00:00 1970 PST 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST 887 | 407 | 00887_update7 | Sun Mar 29 00:00:00 1970 PST 888 | 8 | 00888 | Mon Mar 30 00:00:00 1970 PST 889 | 509 | 00889_update9 | Tue Mar 31 00:00:00 1970 PST 890 | 0 | 00890 | Wed Apr 01 00:00:00 1970 PST 891 | 1 | 00891 | Thu Apr 02 00:00:00 1970 PST 893 | 303 | 00893_update3 | Sat Apr 04 00:00:00 1970 PST 894 | 4 | 00894 | Sun Apr 05 00:00:00 1970 PST 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST 897 | 407 | 00897_update7 | Wed Apr 08 00:00:00 1970 PST 898 | 8 | 00898 | Thu Apr 09 00:00:00 1970 PST 899 | 509 | 00899_update9 | Fri Apr 10 00:00:00 1970 PST 900 | 0 | 00900 | Thu Jan 01 00:00:00 1970 PST 901 | 1 | 00901 | Fri Jan 02 00:00:00 1970 PST 903 | 303 | 00903_update3 | Sun Jan 04 00:00:00 1970 PST 904 | 4 | 00904 | Mon Jan 05 00:00:00 1970 PST 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST 907 | 407 | 00907_update7 | Thu Jan 08 00:00:00 1970 PST 908 | 8 | 00908 | Fri Jan 09 00:00:00 1970 PST 909 | 509 | 00909_update9 | Sat Jan 10 00:00:00 1970 PST 910 | 0 | 00910 | Sun Jan 11 00:00:00 1970 PST 911 | 1 | 00911 | Mon Jan 12 00:00:00 1970 PST 913 | 303 | 00913_update3 | Wed Jan 14 00:00:00 1970 PST 914 | 4 | 00914 | Thu Jan 15 00:00:00 1970 PST 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST 917 | 407 | 00917_update7 | Sun Jan 18 00:00:00 1970 PST 918 | 8 | 00918 | Mon Jan 19 00:00:00 1970 PST 919 | 509 | 00919_update9 | Tue Jan 20 00:00:00 1970 PST 920 | 0 | 00920 | Wed Jan 21 00:00:00 1970 PST 921 | 1 | 00921 | Thu Jan 22 00:00:00 1970 PST 923 | 303 | 00923_update3 | Sat Jan 24 00:00:00 1970 PST 924 | 4 | 00924 | Sun Jan 25 00:00:00 1970 PST 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST 927 | 407 | 00927_update7 | Wed Jan 28 00:00:00 1970 PST 928 | 8 | 00928 | Thu Jan 29 00:00:00 1970 PST 929 | 509 | 00929_update9 | Fri Jan 30 00:00:00 1970 PST 930 | 0 | 00930 | Sat Jan 31 00:00:00 1970 PST 931 | 1 | 00931 | Sun Feb 01 00:00:00 1970 PST 933 | 303 | 00933_update3 | Tue Feb 03 00:00:00 1970 PST 934 | 4 | 00934 | Wed Feb 04 00:00:00 1970 PST 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST 937 | 407 | 00937_update7 | Sat Feb 07 00:00:00 1970 PST 938 | 8 | 00938 | Sun Feb 08 00:00:00 1970 PST 939 | 509 | 00939_update9 | Mon Feb 09 00:00:00 1970 PST 940 | 0 | 00940 | Tue Feb 10 00:00:00 1970 PST 941 | 1 | 00941 | Wed Feb 11 00:00:00 1970 PST 943 | 303 | 00943_update3 | Fri Feb 13 00:00:00 1970 PST 944 | 4 | 00944 | Sat Feb 14 00:00:00 1970 PST 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST 947 | 407 | 00947_update7 | Tue Feb 17 00:00:00 1970 PST 948 | 8 | 00948 | Wed Feb 18 00:00:00 1970 PST 949 | 509 | 00949_update9 | Thu Feb 19 00:00:00 1970 PST 950 | 0 | 00950 | Fri Feb 20 00:00:00 1970 PST 951 | 1 | 00951 | Sat Feb 21 00:00:00 1970 PST 953 | 303 | 00953_update3 | Mon Feb 23 00:00:00 1970 PST 954 | 4 | 00954 | Tue Feb 24 00:00:00 1970 PST 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST 957 | 407 | 00957_update7 | Fri Feb 27 00:00:00 1970 PST 958 | 8 | 00958 | Sat Feb 28 00:00:00 1970 PST 959 | 509 | 00959_update9 | Sun Mar 01 00:00:00 1970 PST 960 | 0 | 00960 | Mon Mar 02 00:00:00 1970 PST 961 | 1 | 00961 | Tue Mar 03 00:00:00 1970 PST 963 | 303 | 00963_update3 | Thu Mar 05 00:00:00 1970 PST 964 | 4 | 00964 | Fri Mar 06 00:00:00 1970 PST 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST 967 | 407 | 00967_update7 | Mon Mar 09 00:00:00 1970 PST 968 | 8 | 00968 | Tue Mar 10 00:00:00 1970 PST 969 | 509 | 00969_update9 | Wed Mar 11 00:00:00 1970 PST 970 | 0 | 00970 | Thu Mar 12 00:00:00 1970 PST 971 | 1 | 00971 | Fri Mar 13 00:00:00 1970 PST 973 | 303 | 00973_update3 | Sun Mar 15 00:00:00 1970 PST 974 | 4 | 00974 | Mon Mar 16 00:00:00 1970 PST 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST 977 | 407 | 00977_update7 | Thu Mar 19 00:00:00 1970 PST 978 | 8 | 00978 | Fri Mar 20 00:00:00 1970 PST 979 | 509 | 00979_update9 | Sat Mar 21 00:00:00 1970 PST 980 | 0 | 00980 | Sun Mar 22 00:00:00 1970 PST 981 | 1 | 00981 | Mon Mar 23 00:00:00 1970 PST 983 | 303 | 00983_update3 | Wed Mar 25 00:00:00 1970 PST 984 | 4 | 00984 | Thu Mar 26 00:00:00 1970 PST 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST 987 | 407 | 00987_update7 | Sun Mar 29 00:00:00 1970 PST 988 | 8 | 00988 | Mon Mar 30 00:00:00 1970 PST 989 | 509 | 00989_update9 | Tue Mar 31 00:00:00 1970 PST 990 | 0 | 00990 | Wed Apr 01 00:00:00 1970 PST 991 | 1 | 00991 | Thu Apr 02 00:00:00 1970 PST 993 | 303 | 00993_update3 | Sat Apr 04 00:00:00 1970 PST 994 | 4 | 00994 | Sun Apr 05 00:00:00 1970 PST 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST 997 | 407 | 00997_update7 | Wed Apr 08 00:00:00 1970 PST 998 | 8 | 00998 | Thu Apr 09 00:00:00 1970 PST 999 | 509 | 00999_update9 | Fri Apr 10 00:00:00 1970 PST 1000 | 0 | 01000 | Thu Jan 01 00:00:00 1970 PST 1001 | 101 | 0000100001 | 1003 | 403 | 0000300003_update3 | 1004 | 104 | 0000400004 | 1006 | 106 | 0000600006 | 1007 | 507 | 0000700007_update7 | 1008 | 108 | 0000800008 | 1009 | 609 | 0000900009_update9 | 1010 | 100 | 0001000010 | 1011 | 101 | 0001100011 | 1013 | 403 | 0001300013_update3 | 1014 | 104 | 0001400014 | 1016 | 106 | 0001600016 | 1017 | 507 | 0001700017_update7 | 1018 | 108 | 0001800018 | 1019 | 609 | 0001900019_update9 | 1020 | 100 | 0002000020 | 1101 | 201 | aaa | 1103 | 503 | ccc_update3 | 1104 | 204 | ddd | (819 rows) --Testcase 300: EXPLAIN (verbose, costs off) INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo'); QUERY PLAN -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Insert on public.ft2 Batch Size: 1 -> Result Output: 1200, 999, NULL::integer, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2 '::character(10), NULL::text (4 rows) --Testcase 301: INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo'); --Testcase 302: EXPLAIN (verbose, costs off) UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200; -- can be pushed down QUERY PLAN --------------------------------------------------------------------------------- Update on public.ft2 -> Foreign Update on public.ft2 SQLite query: UPDATE main."T 1" SET `c3` = 'bar' WHERE ((`C 1` = 1200)) (3 rows) --Testcase 303: UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200; --Testcase 304: EXPLAIN (verbose, costs off) DELETE FROM ft2 WHERE c1 = 1200; -- can be pushed down QUERY PLAN --------------------------------------------------------------------- Delete on public.ft2 -> Foreign Delete on public.ft2 SQLite query: DELETE FROM main."T 1" WHERE ((`C 1` = 1200)) (3 rows) --Testcase 305: DELETE FROM ft2 WHERE c1 = 1200; -- Test UPDATE/DELETE on a three-table join --Testcase 306: INSERT INTO ft2 (c1,c2,c3) SELECT id, id - 1200, to_char(id, 'FM00000') FROM generate_series(1201, 1300) id; --Testcase 307: EXPLAIN (verbose, costs off) UPDATE ft2 SET c3 = 'foo' FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1; -- can be pushed down QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Update on public.ft2 -> Hash Join Output: 'foo'::text, ft2.c1, ft2.*, ft4.*, ft5.* Hash Cond: (ft5.c1 = ft4.c1) -> Foreign Scan on public.ft5 Output: ft5.*, ft5.c1 SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" -> Hash Output: ft2.c1, ft2.*, ft2.c2, ft4.*, ft4.c1 -> Foreign Scan Output: ft2.c1, ft2.*, ft2.c2, ft4.*, ft4.c1 SQLite query: SELECT r1.`C 1`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, r1.`c2`, CASE WHEN ( r2.`c1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) THEN ("(" || COALESCE(r2.`c1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '')|| ")") END, r2.`c1` FROM (main."T 1" r1 INNER JOIN main."T 3" r2 ON (((r1.`c2` = r2.`c1`)) AND ((r1.`C 1` > 1200)))) -> Hash Join Output: ft2.c1, ft2.*, ft2.c2, ft4.*, ft4.c1 Hash Cond: (ft2.c2 = ft4.c1) -> Foreign Scan on public.ft2 Output: ft2.c1, ft2.*, ft2.c2 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > 1200)) -> Hash Output: ft4.*, ft4.c1 -> Foreign Scan on public.ft4 Output: ft4.*, ft4.c1 SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" (23 rows) --Testcase 308: UPDATE ft2 SET c3 = 'foo' FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1; --Testcase 309: SELECT ft2, ft2.*, ft4, ft4.* FROM ft2 INNER JOIN ft4 ON (ft2.c1 > 1200 AND ft2.c2 = ft4.c1) INNER JOIN ft5 ON (ft4.c1 = ft5.c1); ft2 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | ft4 | c1 | c2 | c3 --------------------------------+------+----+-----+----+----+----+------------+----+----------------+----+----+-------- (1206,6,foo,,,,"ft2 ",) | 1206 | 6 | foo | | | | ft2 | | (6,7,AAA006) | 6 | 7 | AAA006 (1212,12,foo,,,,"ft2 ",) | 1212 | 12 | foo | | | | ft2 | | (12,13,AAA012) | 12 | 13 | AAA012 (1218,18,foo,,,,"ft2 ",) | 1218 | 18 | foo | | | | ft2 | | (18,19,AAA018) | 18 | 19 | AAA018 (1224,24,foo,,,,"ft2 ",) | 1224 | 24 | foo | | | | ft2 | | (24,25,AAA024) | 24 | 25 | AAA024 (1230,30,foo,,,,"ft2 ",) | 1230 | 30 | foo | | | | ft2 | | (30,31,AAA030) | 30 | 31 | AAA030 (1236,36,foo,,,,"ft2 ",) | 1236 | 36 | foo | | | | ft2 | | (36,37,AAA036) | 36 | 37 | AAA036 (1242,42,foo,,,,"ft2 ",) | 1242 | 42 | foo | | | | ft2 | | (42,43,AAA042) | 42 | 43 | AAA042 (1248,48,foo,,,,"ft2 ",) | 1248 | 48 | foo | | | | ft2 | | (48,49,AAA048) | 48 | 49 | AAA048 (1254,54,foo,,,,"ft2 ",) | 1254 | 54 | foo | | | | ft2 | | (54,55,AAA054) | 54 | 55 | AAA054 (1260,60,foo,,,,"ft2 ",) | 1260 | 60 | foo | | | | ft2 | | (60,61,AAA060) | 60 | 61 | AAA060 (1266,66,foo,,,,"ft2 ",) | 1266 | 66 | foo | | | | ft2 | | (66,67,AAA066) | 66 | 67 | AAA066 (1272,72,foo,,,,"ft2 ",) | 1272 | 72 | foo | | | | ft2 | | (72,73,AAA072) | 72 | 73 | AAA072 (1278,78,foo,,,,"ft2 ",) | 1278 | 78 | foo | | | | ft2 | | (78,79,AAA078) | 78 | 79 | AAA078 (1284,84,foo,,,,"ft2 ",) | 1284 | 84 | foo | | | | ft2 | | (84,85,AAA084) | 84 | 85 | AAA084 (1290,90,foo,,,,"ft2 ",) | 1290 | 90 | foo | | | | ft2 | | (90,91,AAA090) | 90 | 91 | AAA090 (1296,96,foo,,,,"ft2 ",) | 1296 | 96 | foo | | | | ft2 | | (96,97,AAA096) | 96 | 97 | AAA096 (16 rows) --Testcase 310: EXPLAIN (verbose, costs off) DELETE FROM ft2 USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; -- can be pushed down QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Delete on public.ft2 -> Foreign Scan Output: ft2.c1, ft4.*, ft5.* SQLite query: SELECT r1.`C 1`, CASE WHEN ( r2.`c1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) THEN ("(" || COALESCE(r2.`c1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '')|| ")") END, CASE WHEN ( r3.`c1` IS NOT NULL) OR ( r3.`c2` IS NOT NULL) OR ( r3.`c3` IS NOT NULL) THEN ("(" || COALESCE(r3.`c1`, '') || "," || COALESCE(r3.`c2`, '') || "," || COALESCE(r3.`c3`, '')|| ")") END FROM ((main."T 1" r1 INNER JOIN main."T 3" r2 ON (((r1.`c2` = r2.`c1`)) AND ((r1.`C 1` > 1200)) AND (((r1.`C 1` % 10) = 0)))) LEFT JOIN main."T 4" r3 ON (((r2.`c1` = r3.`c1`)))) -> Hash Left Join Output: ft2.c1, ft4.*, ft5.* Hash Cond: (ft4.c1 = ft5.c1) -> Hash Join Output: ft2.c1, ft4.*, ft4.c1 Hash Cond: (ft2.c2 = ft4.c1) -> Foreign Scan on public.ft2 Output: ft2.c1, ft2.c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` > 1200)) AND (((`C 1` % 10) = 0)) -> Hash Output: ft4.*, ft4.c1 -> Foreign Scan on public.ft4 Output: ft4.*, ft4.c1 SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" -> Hash Output: ft5.*, ft5.c1 -> Foreign Scan on public.ft5 Output: ft5.*, ft5.c1 SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" (23 rows) --Testcase 311: SELECT 100 FROM ft2, ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; ?column? ---------- 100 100 100 100 100 100 100 100 100 100 (10 rows) --Testcase 570: DELETE FROM ft2 USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1) WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1; --Testcase 312: DELETE FROM ft2 WHERE ft2.c1 > 1200; -- Test UPDATE with a MULTIEXPR sub-select -- (maybe someday this'll be remotely executable, but not today) --Testcase 571: EXPLAIN (verbose, costs off) UPDATE ft2 AS target SET (c2, c7) = ( SELECT c2 * 10, c7 FROM ft2 AS src WHERE target.c1 = src.c1 ) WHERE c1 > 1100; QUERY PLAN --------------------------------------------------------------------------------------------------------------------- Update on public.ft2 target -> Foreign Scan on public.ft2 target Output: $1, $2, (SubPlan 1 (returns $1,$2)), target.c1, target.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > 1100)) SubPlan 1 (returns $1,$2) -> Foreign Scan on public.ft2 src Output: (src.c2 * 10), src.c7 SQLite query: SELECT `c2`, `c7` FROM main."T 1" WHERE ((? = `C 1`)) (8 rows) --Testcase 572: UPDATE ft2 AS target SET (c2, c7) = ( SELECT c2 * 10, c7 FROM ft2 AS src WHERE target.c1 = src.c1 ) WHERE c1 > 1100; --Testcase 573: UPDATE ft2 AS target SET (c2) = ( SELECT c2 / 10 FROM ft2 AS src WHERE target.c1 = src.c1 ) WHERE c1 > 1100; -- Test UPDATE involving a join that can be pushed down, -- but a SET clause that can't be EXPLAIN (VERBOSE, COSTS OFF) UPDATE ft2 d SET c2 = CASE WHEN random() >= 0 THEN d.c2 ELSE 0 END FROM ft2 AS t WHERE d.c1 = t.c1 AND d.c1 > 1000; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Update on public.ft2 d -> Foreign Scan Output: CASE WHEN (random() >= '0'::double precision) THEN d.c2 ELSE 0 END, d.c1, d.*, t.* SQLite query: SELECT r1.`c2`, r1.`C 1`, CASE WHEN ( r1.`C 1` IS NOT NULL) OR ( r1.`c2` IS NOT NULL) OR ( r1.`c3` IS NOT NULL) OR ( r1.`c4` IS NOT NULL) OR ( r1.`c5` IS NOT NULL) OR ( r1.`c6` IS NOT NULL) OR ( r1.`c7` IS NOT NULL) OR ( r1.`c8` IS NOT NULL) THEN ("(" || COALESCE(r1.`C 1`, '') || "," || COALESCE(r1.`c2`, '') || "," || COALESCE(r1.`c3`, '') || "," || COALESCE(r1.`c4`, '') || "," || COALESCE(r1.`c5`, '') || "," || COALESCE(r1.`c6`, '') || "," || COALESCE(r1.`c7`, '') || "," || COALESCE(r1.`c8`, '')|| ")") END, CASE WHEN ( r2.`C 1` IS NOT NULL) OR ( r2.`c2` IS NOT NULL) OR ( r2.`c3` IS NOT NULL) OR ( r2.`c4` IS NOT NULL) OR ( r2.`c5` IS NOT NULL) OR ( r2.`c6` IS NOT NULL) OR ( r2.`c7` IS NOT NULL) OR ( r2.`c8` IS NOT NULL) THEN ("(" || COALESCE(r2.`C 1`, '') || "," || COALESCE(r2.`c2`, '') || "," || COALESCE(r2.`c3`, '') || "," || COALESCE(r2.`c4`, '') || "," || COALESCE(r2.`c5`, '') || "," || COALESCE(r2.`c6`, '') || "," || COALESCE(r2.`c7`, '') || "," || COALESCE(r2.`c8`, '')|| ")") END FROM (main."T 1" r1 INNER JOIN main."T 1" r2 ON (((r1.`C 1` = r2.`C 1`)) AND ((r1.`C 1` > 1000)))) -> Hash Join Output: d.c2, d.c1, d.*, t.* Hash Cond: (d.c1 = t.c1) -> Foreign Scan on public.ft2 d Output: d.c2, d.c1, d.* SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > 1000)) -> Hash Output: t.*, t.c1 -> Foreign Scan on public.ft2 t Output: t.*, t.c1 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (15 rows) UPDATE ft2 d SET c2 = CASE WHEN random() >= 0 THEN d.c2 ELSE 0 END FROM ft2 AS t WHERE d.c1 = t.c1 AND d.c1 > 1000; -- Test UPDATE/DELETE with WHERE or JOIN/ON conditions containing -- user-defined operators/functions --ALTER SERVER loopback OPTIONS (DROP extensions); --Testcase 574: INSERT INTO ft2 (c1,c2,c3) SELECT id, id % 10, to_char(id, 'FM00000') FROM generate_series(2001, 2010) id; --Testcase 575: EXPLAIN (verbose, costs off) UPDATE ft2 SET c3 = 'bar' WHERE sqlite_fdw_abs(c1) > 2000; -- can't be pushed down QUERY PLAN ---------------------------------------------------------------------------------------------- Update on public.ft2 -> Foreign Scan on public.ft2 Output: 'bar'::text, c1, ft2.* Filter: (sqlite_fdw_abs(ft2.c1) > 2000) SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" (5 rows) --Testcase 576: UPDATE ft2 SET c3 = 'bar' WHERE sqlite_fdw_abs(c1) > 2000; --Testcase 577: SELECT * FROM ft2 WHERE sqlite_fdw_abs(c1) > 2000; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+----+-----+----+----+----+------------+---- 2001 | 1 | bar | | | | ft2 | 2002 | 2 | bar | | | | ft2 | 2003 | 3 | bar | | | | ft2 | 2004 | 4 | bar | | | | ft2 | 2005 | 5 | bar | | | | ft2 | 2006 | 6 | bar | | | | ft2 | 2007 | 7 | bar | | | | ft2 | 2008 | 8 | bar | | | | ft2 | 2009 | 9 | bar | | | | ft2 | 2010 | 0 | bar | | | | ft2 | (10 rows) --Testcase 578: EXPLAIN (verbose, costs off) UPDATE ft2 SET c3 = 'baz' FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; -- can't be pushed down QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------- Update on public.ft2 -> Nested Loop Output: 'baz'::text, ft2.c1, ft2.*, ft4.*, ft5.* Join Filter: (ft2.c2 === ft4.c1) -> Hash Join Output: ft4.*, ft4.c1, ft5.* Hash Cond: (ft4.c1 = ft5.c1) -> Foreign Scan on public.ft4 Output: ft4.*, ft4.c1 SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" -> Hash Output: ft5.*, ft5.c1 -> Foreign Scan on public.ft5 Output: ft5.*, ft5.c1 SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" -> Materialize Output: ft2.c1, ft2.*, ft2.c2 -> Foreign Scan on public.ft2 Output: ft2.c1, ft2.*, ft2.c2 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" WHERE ((`C 1` > 2000)) (20 rows) --Testcase 579: UPDATE ft2 SET c3 = 'baz' FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; --Testcase 580: SELECT ft2.*, ft4.*, ft5.* FROM ft2, ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1) WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c1 | c2 | c3 ------+----+-----+----+----+----+------------+----+----+----+--------+----+----+-------- 2006 | 6 | baz | | | | ft2 | | 6 | 7 | AAA006 | 6 | 7 | AAA006 (1 row) --Testcase 581: EXPLAIN (verbose, costs off) DELETE FROM ft2 USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; -- can't be pushed down QUERY PLAN --------------------------------------------------------------------------------------------------- Delete on public.ft2 -> Nested Loop Output: ft2.c1, ft4.*, ft5.* Join Filter: (ft4.c1 === ft5.c1) -> Hash Join Output: ft2.c1, ft4.*, ft4.c1 Hash Cond: (ft4.c1 = ft2.c2) -> Foreign Scan on public.ft4 Output: ft4.*, ft4.c1 SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 3" -> Hash Output: ft2.c1, ft2.c2 -> Foreign Scan on public.ft2 Output: ft2.c1, ft2.c2 SQLite query: SELECT `C 1`, `c2` FROM main."T 1" WHERE ((`C 1` > 2000)) -> Materialize Output: ft5.*, ft5.c1 -> Foreign Scan on public.ft5 Output: ft5.*, ft5.c1 SQLite query: SELECT `c1`, `c2`, `c3` FROM main."T 4" (20 rows) --Testcase 582: SELECT ft2.c1, ft2.c2, ft2.c3 FROM ft2, ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; -- can't be pushed down c1 | c2 | c3 ------+----+----- 2006 | 6 | baz (1 row) --Testcase 583: DELETE FROM ft2 USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1) WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1; --Testcase 584: DELETE FROM ft2 WHERE ft2.c1 > 2000; --ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw'); -- Test that trigger on remote table works as expected --Testcase 585: CREATE OR REPLACE FUNCTION "S 1".F_BRTRIG() RETURNS trigger AS $$ BEGIN NEW.c3 = NEW.c3 || '_trig_update'; RETURN NEW; END; $$ LANGUAGE plpgsql; --Testcase 586: CREATE TRIGGER t1_br_insert BEFORE INSERT OR UPDATE ON ft2 FOR EACH ROW EXECUTE PROCEDURE "S 1".F_BRTRIG(); --Testcase 313: INSERT INTO ft2 (c1,c2,c3) VALUES (1208, 818, 'fff'); --Testcase 314: SELECT * FROM ft2 WHERE c1 = 1208; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+-----+-----------------+----+----+----+------------+---- 1208 | 818 | fff_trig_update | | | | ft2 | (1 row) --Testcase 315: INSERT INTO ft2 (c1,c2,c3,c6) VALUES (1218, 818, 'ggg', '(--;'); --Testcase 316: SELECT * FROM ft2 WHERE c1 = 1218; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+-----+-----------------+----+----+------+------------+---- 1218 | 818 | ggg_trig_update | | | (--; | ft2 | (1 row) --Testcase 317: UPDATE ft2 SET c2 = c2 + 600, c3 = c3 WHERE c1 % 10 = 8 AND c1 < 1200; --Testcase 318: SELECT * FROM ft2 WHERE c1 % 10 = 8 AND c1 < 1200; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+-----+------------------------+------------------------------+--------------------------+----+------------+----- 8 | 608 | 00008_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 18 | 608 | 00018_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo 28 | 608 | 00028_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo 38 | 608 | 00038_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo 48 | 608 | 00048_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo 58 | 608 | 00058_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo 68 | 608 | 00068_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo 78 | 608 | 00078_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo 88 | 608 | 00088_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo 98 | 608 | 00098_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo 108 | 608 | 00108_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 118 | 608 | 00118_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo 128 | 608 | 00128_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo 138 | 608 | 00138_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo 148 | 608 | 00148_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo 158 | 608 | 00158_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo 168 | 608 | 00168_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo 178 | 608 | 00178_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo 188 | 608 | 00188_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo 198 | 608 | 00198_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo 208 | 608 | 00208_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 218 | 608 | 00218_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo 228 | 608 | 00228_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo 238 | 608 | 00238_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo 248 | 608 | 00248_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo 258 | 608 | 00258_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo 268 | 608 | 00268_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo 278 | 608 | 00278_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo 288 | 608 | 00288_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo 298 | 608 | 00298_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo 308 | 608 | 00308_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 318 | 608 | 00318_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo 328 | 608 | 00328_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo 338 | 608 | 00338_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo 348 | 608 | 00348_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo 358 | 608 | 00358_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo 368 | 608 | 00368_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo 378 | 608 | 00378_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo 388 | 608 | 00388_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo 398 | 608 | 00398_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo 408 | 608 | 00408_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 418 | 608 | 00418_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo 428 | 608 | 00428_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo 438 | 608 | 00438_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo 448 | 608 | 00448_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo 458 | 608 | 00458_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo 468 | 608 | 00468_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo 478 | 608 | 00478_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo 488 | 608 | 00488_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo 498 | 608 | 00498_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo 508 | 608 | 00508_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 518 | 608 | 00518_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo 528 | 608 | 00528_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo 538 | 608 | 00538_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo 548 | 608 | 00548_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo 558 | 608 | 00558_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo 568 | 608 | 00568_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo 578 | 608 | 00578_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo 588 | 608 | 00588_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo 598 | 608 | 00598_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo 608 | 608 | 00608_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 618 | 608 | 00618_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo 628 | 608 | 00628_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo 638 | 608 | 00638_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo 648 | 608 | 00648_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo 658 | 608 | 00658_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo 668 | 608 | 00668_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo 678 | 608 | 00678_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo 688 | 608 | 00688_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo 698 | 608 | 00698_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo 708 | 608 | 00708_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 718 | 608 | 00718_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo 728 | 608 | 00728_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo 738 | 608 | 00738_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo 748 | 608 | 00748_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo 758 | 608 | 00758_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo 768 | 608 | 00768_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo 778 | 608 | 00778_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo 788 | 608 | 00788_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo 798 | 608 | 00798_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo 808 | 608 | 00808_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 818 | 608 | 00818_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo 828 | 608 | 00828_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo 838 | 608 | 00838_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo 848 | 608 | 00848_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo 858 | 608 | 00858_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo 868 | 608 | 00868_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo 878 | 608 | 00878_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo 888 | 608 | 00888_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo 898 | 608 | 00898_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo 908 | 608 | 00908_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo 918 | 608 | 00918_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo 928 | 608 | 00928_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo 938 | 608 | 00938_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo 948 | 608 | 00948_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo 958 | 608 | 00958_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo 968 | 608 | 00968_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo 978 | 608 | 00978_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo 988 | 608 | 00988_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo 998 | 608 | 00998_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo 1008 | 708 | 0000800008_trig_update | | | | ft2 | 1018 | 708 | 0001800018_trig_update | | | | ft2 | (102 rows) -- Test errors thrown on remote side during update -- create table in the remote server with check contraint --Testcase 738: CREATE FOREIGN TABLE ft1_constraint ( c1 int OPTIONS (key 'true'), c2 int NOT NULL, c3 text, c4 timestamptz, c5 timestamp, c6 varchar(10), c7 char(10) default 'ft1', c8 text ) SERVER sqlite_svr OPTIONS (table 't1_constraint'); --Testcase 747: INSERT INTO ft1_constraint SELECT * FROM ft1 ON CONFLICT DO NOTHING; -- c2 must be greater than or equal to 0, so this case is ignored. --Testcase 754: INSERT INTO ft1_constraint(c1, c2) VALUES (2222, -2) ON CONFLICT DO NOTHING; -- ignore, do nothing --Testcase 755: SELECT c1, c2 FROM ft1_constraint WHERE c1 = 2222 or c2 = -2; -- empty result c1 | c2 ----+---- (0 rows) --Testcase 748: ALTER FOREIGN TABLE ft1 RENAME TO ft1_org; --Testcase 749: ALTER FOREIGN TABLE ft1_constraint RENAME TO ft1; --Testcase 319: INSERT INTO ft1(c1, c2) VALUES(11, 12); -- duplicate key ERROR: failed to execute remote SQL: rc=19 UNIQUE constraint failed: t1_constraint.c1 sql=INSERT INTO main."t1_constraint"(`c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`) VALUES (?, ?, ?, ?, ?, ?, ?, ?) --Testcase 320: INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO NOTHING; -- unsupported ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification --Testcase 321: INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO UPDATE SET c3 = 'ffg'; -- unsupported ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification --Testcase 743: INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive ERROR: failed to execute remote SQL: rc=19 CHECK constraint failed: c2 >= 0 sql=INSERT INTO main."t1_constraint"(`c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`) VALUES (?, ?, ?, ?, ?, ?, ?, ?) --Testcase 744: UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive ERROR: failed to execute remote SQL: rc=19 CHECK constraint failed: c2 >= 0 sql=UPDATE main."t1_constraint" SET `c2` = (- `c2`) WHERE ((`c1` = 1)) --Testcase 750: ALTER FOREIGN TABLE ft1 RENAME TO ft1_constraint; --Testcase 751: ALTER FOREIGN TABLE ft1_org RENAME TO ft1; -- Test savepoint/rollback behavior --Testcase 322: select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; c2 | count -----+------- 0 | 100 1 | 100 4 | 100 6 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) --Testcase 323: select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; c2 | count -----+------- 0 | 100 1 | 100 4 | 100 6 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) begin; --Testcase 324: update ft2 set c2 = 42 where c2 = 0; --Testcase 325: select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 4 | 100 6 | 100 42 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) savepoint s1; --Testcase 326: update ft2 set c2 = 44 where c2 = 4; --Testcase 327: select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 6 | 100 42 | 100 44 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) release savepoint s1; --Testcase 328: select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 6 | 100 42 | 100 44 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) savepoint s2; --Testcase 329: update ft2 set c2 = 46 where c2 = 6; --Testcase 330: select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 42 | 100 44 | 100 46 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) rollback to savepoint s2; --Testcase 331: select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 6 | 100 42 | 100 44 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) release savepoint s2; --Testcase 332: select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 6 | 100 42 | 100 44 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) savepoint s3; --Testcase 333: --skip, does not support CHECK --update ft2 set c2 = -2 where c2 = 42 and c1 = 10; -- fail on remote side rollback to savepoint s3; --Testcase 334: select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 6 | 100 42 | 100 44 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) release savepoint s3; --Testcase 335: select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 6 | 100 42 | 100 44 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) -- none of the above is committed yet remotely --Testcase 336: select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 6 | 100 42 | 100 44 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) commit; --Testcase 337: select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 6 | 100 42 | 100 44 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) --Testcase 338: select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1; c2 | count -----+------- 1 | 100 6 | 100 42 | 100 44 | 100 100 | 2 101 | 2 104 | 2 106 | 2 201 | 1 204 | 1 303 | 100 403 | 2 407 | 100 (13 rows) --VACUUM ANALYZE "S 1"."T 1"; -- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs -- FIRST behavior here. -- ORDER BY DESC NULLS LAST options --Testcase 339: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c6` DESC NULLS LAST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 795 (3 rows) --Testcase 340: SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+-----+--------------------+------------------------------+--------------------------+------+------------+----- 960 | 42 | 00960_trig_update | Mon Mar 02 00:00:00 1970 PST | Mon Mar 02 00:00:00 1970 | 0 | 0 | foo 970 | 42 | 00970_trig_update | Thu Mar 12 00:00:00 1970 PST | Thu Mar 12 00:00:00 1970 | 0 | 0 | foo 980 | 42 | 00980_trig_update | Sun Mar 22 00:00:00 1970 PST | Sun Mar 22 00:00:00 1970 | 0 | 0 | foo 990 | 42 | 00990_trig_update | Wed Apr 01 00:00:00 1970 PST | Wed Apr 01 00:00:00 1970 | 0 | 0 | foo 1000 | 42 | 01000_trig_update | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0 | 0 | foo 1218 | 818 | ggg_trig_update | | | (--; | ft2 | 1001 | 101 | 0000100001 | | | | ft2 | 1003 | 403 | 0000300003_update3 | | | | ft2 | 1004 | 104 | 0000400004 | | | | ft2 | 1006 | 106 | 0000600006 | | | | ft2 | (10 rows) -- ORDER BY DESC NULLS FIRST options --Testcase 341: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10; QUERY PLAN ---------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c6` DESC NULLS FIRST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 15 (3 rows) --Testcase 342: SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+-----+-----------------+------------------------------+--------------------------+----+------------+----- 1020 | 100 | 0002000020 | | | | ft2 | 1101 | 201 | aaa | | | | ft2 | 1103 | 503 | ccc_update3 | | | | ft2 | 1104 | 204 | ddd | | | | ft2 | 1208 | 818 | fff_trig_update | | | | ft2 | 9 | 509 | 00009_update9 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | ft2 | foo 19 | 509 | 00019_update9 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | ft2 | foo 29 | 509 | 00029_update9 | Fri Jan 30 00:00:00 1970 PST | Fri Jan 30 00:00:00 1970 | 9 | ft2 | foo 39 | 509 | 00039_update9 | Mon Feb 09 00:00:00 1970 PST | Mon Feb 09 00:00:00 1970 | 9 | ft2 | foo 49 | 509 | 00049_update9 | Thu Feb 19 00:00:00 1970 PST | Thu Feb 19 00:00:00 1970 | 9 | ft2 | foo (10 rows) -- ORDER BY ASC NULLS FIRST options --Testcase 343: EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10; QUERY PLAN --------------------------------------------------------------------------------------------------------------------------------------------------------------- Foreign Scan on public.ft1 Output: c1, c2, c3, c4, c5, c6, c7, c8 SQLite query: SELECT `C 1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8` FROM main."T 1" ORDER BY `c6` ASC NULLS FIRST, `C 1` ASC NULLS LAST LIMIT 10 OFFSET 15 (3 rows) --Testcase 344: SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10; c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 ------+-----+-------------------+------------------------------+--------------------------+------+------------+----- 1020 | 100 | 0002000020 | | | | ft2 | 1101 | 201 | aaa | | | | ft2 | 1103 | 503 | ccc_update3 | | | | ft2 | 1104 | 204 | ddd | | | | ft2 | 1208 | 818 | fff_trig_update | | | | ft2 | 1218 | 818 | ggg_trig_update | | | (--; | ft2 | 10 | 42 | 00010_trig_update | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo 20 | 42 | 00020_trig_update | Wed Jan 21 00:00:00 1970 PST | Wed Jan 21 00:00:00 1970 | 0 | 0 | foo 30 | 42 | 00030_trig_update | Sat Jan 31 00:00:00 1970 PST | Sat Jan 31 00:00:00 1970 | 0 | 0 | foo 40 | 42 | 00040_trig_update | Tue Feb 10 00:00:00 1970 PST | Tue Feb 10 00:00:00 1970 | 0 | 0 | foo (10 rows) -- =================================================================== -- test check constraints -- =================================================================== --Testcase 752: ALTER FOREIGN TABLE ft1 RENAME TO ft1_org; --Testcase 753: ALTER FOREIGN TABLE ft1_constraint RENAME TO ft1; -- Consistent check constraints provide consistent results ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK (c2 >= 0); --Testcase 587: EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0; QUERY PLAN ------------------------------------------------------------------------------ Foreign Scan Output: (count(*)) SQLite query: SELECT count(*) FROM main."t1_constraint" WHERE ((`c2` < 0)) (3 rows) --Testcase 588: SELECT count(*) FROM ft1 WHERE c2 < 0; count ------- 0 (1 row) SET constraint_exclusion = 'on'; --Testcase 589: EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0; QUERY PLAN -------------------------------- Aggregate Output: count(*) -> Result One-Time Filter: false (4 rows) --Testcase 590: SELECT count(*) FROM ft1 WHERE c2 < 0; count ------- 0 (1 row) RESET constraint_exclusion; -- check constraint is enforced on the remote side, not locally --Testcase 745: INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive ERROR: failed to execute remote SQL: rc=19 CHECK constraint failed: c2 >= 0 sql=INSERT INTO main."t1_constraint"(`c1`, `c2`, `c3`, `c4`, `c5`, `c6`, `c7`, `c8`) VALUES (?, ?, ?, ?, ?, ?, ?, ?) --Testcase 746: UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive ERROR: failed to execute remote SQL: rc=19 CHECK constraint failed: c2 >= 0 sql=UPDATE main."t1_constraint" SET `c2` = (- `c2`) WHERE ((`c1` = 1)) ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive; -- But inconsistent check constraints provide inconsistent results ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK (c2 < 0); --Testcase 591: EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0; QUERY PLAN ------------------------------------------------------------------------------- Foreign Scan Output: (count(*)) SQLite query: SELECT count(*) FROM main."t1_constraint" WHERE ((`c2` >= 0)) (3 rows) --Testcase 592: SELECT count(*) FROM ft1 WHERE c2 >= 0; count ------- 821 (1 row) SET constraint_exclusion = 'on'; --Testcase 593: EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0; QUERY PLAN -------------------------------- Aggregate Output: count(*) -> Result One-Time Filter: false (4 rows) --Testcase 594: SELECT count(*) FROM ft1 WHERE c2 >= 0; count ------- 0 (1 row) RESET constraint_exclusion; -- local check constraint is not actually enforced --Testcase 595: INSERT INTO ft1(c1, c2) VALUES(1111, 2); --Testcase 596: UPDATE ft1 SET c2 = c2 + 1 WHERE c1 = 1; ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2negative; -- =================================================================== -- test WITH CHECK OPTION constraints -- =================================================================== --Testcase 597: CREATE FUNCTION row_before_insupd_trigfunc() RETURNS trigger AS $$BEGIN NEW.a := NEW.a + 10; RETURN NEW; END$$ LANGUAGE plpgsql; --Testcase 598: CREATE FOREIGN TABLE foreign_tbl (a int OPTIONS (key 'true'), b int) SERVER sqlite_svr; --Testcase 599: CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON foreign_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc(); --Testcase 600: CREATE VIEW rw_view AS SELECT * FROM foreign_tbl WHERE a < b WITH CHECK OPTION; --Testcase 601: \d+ rw_view View "public.rw_view" Column | Type | Collation | Nullable | Default | Storage | Description --------+---------+-----------+----------+---------+---------+------------- a | integer | | | | plain | b | integer | | | | plain | View definition: SELECT foreign_tbl.a, foreign_tbl.b FROM foreign_tbl WHERE foreign_tbl.a < foreign_tbl.b; Options: check_option=cascaded --Testcase 345: EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO rw_view VALUES (0, 5); QUERY PLAN ------------------------------ Insert on public.foreign_tbl Batch Size: 1 -> Result Output: 0, 5 (4 rows) --Testcase 602: INSERT INTO rw_view VALUES (0, 5); -- should fail ERROR: new row violates check option for view "rw_view" DETAIL: Failing row contains (10, 5). --Testcase 603: EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO rw_view VALUES (0, 15); QUERY PLAN ------------------------------ Insert on public.foreign_tbl Batch Size: 1 -> Result Output: 0, 15 (4 rows) --Testcase 604: INSERT INTO rw_view VALUES (0, 15); -- error --Testcase 605: SELECT * FROM foreign_tbl; a | b ----+---- 10 | 15 (1 row) --Testcase 606: EXPLAIN (VERBOSE, COSTS OFF) UPDATE rw_view SET b = b + 5; QUERY PLAN ----------------------------------------------------------------------------------- Update on public.foreign_tbl -> Foreign Scan on public.foreign_tbl Output: (foreign_tbl.b + 5), foreign_tbl.a, foreign_tbl.* SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) (4 rows) --Testcase 607: UPDATE rw_view SET b = b + 5; -- should fail ERROR: new row violates check option for view "rw_view" DETAIL: Failing row contains (20, 20). --Testcase 608: EXPLAIN (VERBOSE, COSTS OFF) UPDATE rw_view SET b = b + 15; QUERY PLAN ----------------------------------------------------------------------------------- Update on public.foreign_tbl -> Foreign Scan on public.foreign_tbl Output: (foreign_tbl.b + 15), foreign_tbl.a, foreign_tbl.* SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) (4 rows) --Testcase 609: UPDATE rw_view SET b = b + 15; -- ok --Testcase 610: SELECT * FROM foreign_tbl; a | b ----+---- 20 | 30 (1 row) --Testcase 611: DROP FOREIGN TABLE foreign_tbl CASCADE; NOTICE: drop cascades to view rw_view --Testcase 612: DROP TRIGGER row_before_insupd_trigger ON foreign_tbl; ERROR: relation "foreign_tbl" does not exist -- test WCO for partitions --Testcase 613: CREATE FOREIGN TABLE foreign_tbl (a int OPTIONS (key 'true'), b int) SERVER sqlite_svr; --Testcase 614: CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON foreign_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc(); --Testcase 615: CREATE TABLE parent_tbl (a int, b int) PARTITION BY RANGE(a); ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100); --Testcase 616: CREATE VIEW rw_view AS SELECT * FROM parent_tbl WHERE a < b WITH CHECK OPTION; --Testcase 617: \d+ rw_view View "public.rw_view" Column | Type | Collation | Nullable | Default | Storage | Description --------+---------+-----------+----------+---------+---------+------------- a | integer | | | | plain | b | integer | | | | plain | View definition: SELECT parent_tbl.a, parent_tbl.b FROM parent_tbl WHERE parent_tbl.a < parent_tbl.b; Options: check_option=cascaded --Testcase 618: EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO rw_view VALUES (0, 5); QUERY PLAN ----------------------------- Insert on public.parent_tbl -> Result Output: 0, 5 (3 rows) --Testcase 619: INSERT INTO rw_view VALUES (0, 5); -- should fail ERROR: Not support partition insert --Testcase 620: EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO rw_view VALUES (0, 15); QUERY PLAN ----------------------------- Insert on public.parent_tbl -> Result Output: 0, 15 (3 rows) --Testcase 621: INSERT INTO rw_view VALUES (0, 15); -- ok ERROR: Not support partition insert --Testcase 622: SELECT * FROM foreign_tbl; a | b ----+---- 20 | 30 (1 row) --Testcase 623: EXPLAIN (VERBOSE, COSTS OFF) UPDATE rw_view SET b = b + 5; QUERY PLAN --------------------------------------------------------------------------------------------- Update on public.parent_tbl Foreign Update on public.foreign_tbl parent_tbl_1 -> Foreign Scan on public.foreign_tbl parent_tbl_1 Output: (parent_tbl_1.b + 5), parent_tbl_1.tableoid, parent_tbl_1.a, parent_tbl_1.* SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) (5 rows) --Testcase 624: UPDATE rw_view SET b = b + 5; -- should fail --Testcase 625: EXPLAIN (VERBOSE, COSTS OFF) UPDATE rw_view SET b = b + 15; QUERY PLAN ---------------------------------------------------------------------------------------------- Update on public.parent_tbl Foreign Update on public.foreign_tbl parent_tbl_1 -> Foreign Scan on public.foreign_tbl parent_tbl_1 Output: (parent_tbl_1.b + 15), parent_tbl_1.tableoid, parent_tbl_1.a, parent_tbl_1.* SQLite query: SELECT `a`, `b` FROM main."foreign_tbl" WHERE ((`a` < `b`)) (5 rows) --Testcase 626: UPDATE rw_view SET b = b + 15; -- ok --Testcase 627: SELECT * FROM foreign_tbl; a | b ----+---- 40 | 50 (1 row) --Testcase 628: DROP TRIGGER row_before_insupd_trigger ON foreign_tbl; --Testcase 629: DROP FOREIGN TABLE foreign_tbl CASCADE; --Testcase 630: DROP TABLE parent_tbl CASCADE; NOTICE: drop cascades to view rw_view --Testcase 631: DROP FUNCTION row_before_insupd_trigfunc; -- =================================================================== -- test serial columns (ie, sequence-based defaults) -- =================================================================== --Testcase 632: create foreign table loc1 (f1 serial, f2 text, id integer options (key 'true')) server sqlite_svr; --Testcase 633: create foreign table rem1 (f1 serial, f2 text, id integer options (key 'true')) server sqlite_svr options(table 'loc1'); --Testcase 352: select pg_catalog.setval('rem1_f1_seq', 10, false); setval -------- 10 (1 row) --Testcase 353: insert into loc1(f2) values('hi'); --Testcase 634: insert into rem1(f2) values('hi remote'); --Testcase 354: insert into loc1(f2) values('bye'); --Testcase 635: insert into rem1(f2) values('bye remote'); --Testcase 355: select f1, f2 from loc1; f1 | f2 ----+------------ 1 | hi 10 | hi remote 2 | bye 11 | bye remote (4 rows) --Testcase 636: select f1, f2 from rem1; f1 | f2 ----+------------ 1 | hi 10 | hi remote 2 | bye 11 | bye remote (4 rows) -- =================================================================== -- test generated columns -- =================================================================== --Testcase 637: create foreign table grem1 ( a int options (key 'true'), b int generated always as (a * 2) stored) server sqlite_svr; --Testcase 638: insert into grem1 (a) values (1), (2); --Testcase 639: update grem1 set a = 22 where a = 2; --Testcase 640: select * from grem1; a | b ----+---- 1 | 2 22 | 44 (2 rows) -- =================================================================== -- test local triggers -- =================================================================== -- Trigger functions "borrowed" from triggers regress test. --Testcase 641: 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;$$; --Testcase 642: CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE ON rem1 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); --Testcase 643: CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE ON rem1 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); --Testcase 644: CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger LANGUAGE plpgsql AS $$ declare oldnew text[]; relid text; argstr text; begin relid := TG_relid::regclass; argstr := ''; 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 '%(%) % % % ON %', tg_name, argstr, TG_when, TG_level, TG_OP, relid; oldnew := '{}'::text[]; if TG_OP != 'INSERT' then oldnew := array_append(oldnew, format('OLD: %s', OLD)); end if; if TG_OP != 'DELETE' then oldnew := array_append(oldnew, format('NEW: %s', NEW)); end if; RAISE NOTICE '%', array_to_string(oldnew, ','); if TG_OP = 'DELETE' then return OLD; else return NEW; end if; end; $$; -- Test basic functionality --Testcase 645: CREATE TRIGGER trig_row_before BEFORE INSERT OR UPDATE OR DELETE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 646: CREATE TRIGGER trig_row_after AFTER INSERT OR UPDATE OR DELETE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 356: delete from rem1; NOTICE: trigger_func() called: action = DELETE, when = BEFORE, level = STATEMENT NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 NOTICE: OLD: (1,hi,1) NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 NOTICE: OLD: (10,"hi remote",2) NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 NOTICE: OLD: (2,bye,3) NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1 NOTICE: OLD: (11,"bye remote",4) NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 NOTICE: OLD: (1,hi,1) NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 NOTICE: OLD: (10,"hi remote",2) NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 NOTICE: OLD: (2,bye,3) NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1 NOTICE: OLD: (11,"bye remote",4) NOTICE: trigger_func() called: action = DELETE, when = AFTER, level = STATEMENT --Testcase 357: insert into rem1 values(1,'insert'); NOTICE: trigger_func() called: action = INSERT, when = BEFORE, level = STATEMENT NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1 NOTICE: NEW: (1,insert,) NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 NOTICE: NEW: (1,insert,) NOTICE: trigger_func() called: action = INSERT, when = AFTER, level = STATEMENT --Testcase 358: update rem1 set f2 = 'update' where f1 = 1; NOTICE: trigger_func() called: action = UPDATE, when = BEFORE, level = STATEMENT NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1 NOTICE: OLD: (1,insert,5),NEW: (1,update,5) NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1 NOTICE: OLD: (1,insert,5),NEW: (1,update,5) NOTICE: trigger_func() called: action = UPDATE, when = AFTER, level = STATEMENT --Testcase 359: update rem1 set f2 = f2 || f2; NOTICE: trigger_func() called: action = UPDATE, when = BEFORE, level = STATEMENT NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1 NOTICE: OLD: (1,update,5),NEW: (1,updateupdate,5) NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1 NOTICE: OLD: (1,update,5),NEW: (1,updateupdate,5) NOTICE: trigger_func() called: action = UPDATE, when = AFTER, level = STATEMENT -- cleanup --Testcase 647: DROP TRIGGER trig_row_before ON rem1; --Testcase 648: DROP TRIGGER trig_row_after ON rem1; --Testcase 649: DROP TRIGGER trig_stmt_before ON rem1; --Testcase 650: DROP TRIGGER trig_stmt_after ON rem1; --Testcase 360: DELETE from rem1; -- Test multiple AFTER ROW triggers on a foreign table --Testcase 651: CREATE TRIGGER trig_row_after1 AFTER INSERT OR UPDATE OR DELETE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 652: CREATE TRIGGER trig_row_after2 AFTER INSERT OR UPDATE OR DELETE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 653: insert into rem1 values(1,'insert'); NOTICE: trig_row_after1(23, skidoo) AFTER ROW INSERT ON rem1 NOTICE: NEW: (1,insert,) NOTICE: trig_row_after2(23, skidoo) AFTER ROW INSERT ON rem1 NOTICE: NEW: (1,insert,) --Testcase 654: update rem1 set f2 = 'update' where f1 = 1; NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1 NOTICE: OLD: (1,insert,6),NEW: (1,update,6) NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1 NOTICE: OLD: (1,insert,6),NEW: (1,update,6) --Testcase 655: update rem1 set f2 = f2 || f2; NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1 NOTICE: OLD: (1,update,6),NEW: (1,updateupdate,6) NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1 NOTICE: OLD: (1,update,6),NEW: (1,updateupdate,6) --Testcase 656: delete from rem1; NOTICE: trig_row_after1(23, skidoo) AFTER ROW DELETE ON rem1 NOTICE: OLD: (1,updateupdate,6) NOTICE: trig_row_after2(23, skidoo) AFTER ROW DELETE ON rem1 NOTICE: OLD: (1,updateupdate,6) -- cleanup --Testcase 657: DROP TRIGGER trig_row_after1 ON rem1; --Testcase 658: DROP TRIGGER trig_row_after2 ON rem1; -- Test WHEN conditions --Testcase 659: CREATE TRIGGER trig_row_before_insupd BEFORE INSERT OR UPDATE ON rem1 FOR EACH ROW WHEN (NEW.f2 like '%update%') EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 660: CREATE TRIGGER trig_row_after_insupd AFTER INSERT OR UPDATE ON rem1 FOR EACH ROW WHEN (NEW.f2 like '%update%') EXECUTE PROCEDURE trigger_data(23,'skidoo'); -- Insert or update not matching: nothing happens --Testcase 363: INSERT INTO rem1 values(1, 'insert'); --Testcase 364: UPDATE rem1 set f2 = 'test'; -- Insert or update matching: triggers are fired --Testcase 365: INSERT INTO rem1 values(2, 'update'); NOTICE: trig_row_before_insupd(23, skidoo) BEFORE ROW INSERT ON rem1 NOTICE: NEW: (2,update,) NOTICE: trig_row_after_insupd(23, skidoo) AFTER ROW INSERT ON rem1 NOTICE: NEW: (2,update,) --Testcase 366: UPDATE rem1 set f2 = 'update update' where f1 = '2'; NOTICE: trig_row_before_insupd(23, skidoo) BEFORE ROW UPDATE ON rem1 NOTICE: OLD: (2,update,8),NEW: (2,"update update",8) NOTICE: trig_row_after_insupd(23, skidoo) AFTER ROW UPDATE ON rem1 NOTICE: OLD: (2,update,8),NEW: (2,"update update",8) --Testcase 661: CREATE TRIGGER trig_row_before_delete BEFORE DELETE ON rem1 FOR EACH ROW WHEN (OLD.f2 like '%update%') EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 662: CREATE TRIGGER trig_row_after_delete AFTER DELETE ON rem1 FOR EACH ROW WHEN (OLD.f2 like '%update%') EXECUTE PROCEDURE trigger_data(23,'skidoo'); -- Trigger is fired for f1=2, not for f1=1 --Testcase 369: DELETE FROM rem1; NOTICE: trig_row_before_delete(23, skidoo) BEFORE ROW DELETE ON rem1 NOTICE: OLD: (2,"update update",8) NOTICE: trig_row_after_delete(23, skidoo) AFTER ROW DELETE ON rem1 NOTICE: OLD: (2,"update update",8) -- cleanup --Testcase 663: DROP TRIGGER trig_row_before_insupd ON rem1; --Testcase 664: DROP TRIGGER trig_row_after_insupd ON rem1; --Testcase 665: DROP TRIGGER trig_row_before_delete ON rem1; --Testcase 666: DROP TRIGGER trig_row_after_delete ON rem1; -- Test various RETURN statements in BEFORE triggers. --Testcase 667: CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$ BEGIN NEW.f2 := NEW.f2 || ' triggered !'; RETURN NEW; END $$ language plpgsql; --Testcase 668: CREATE TRIGGER trig_row_before_insupd BEFORE INSERT OR UPDATE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); -- The new values should have 'triggered' appended --Testcase 370: INSERT INTO rem1 values(1, 'insert'); --Testcase 371: SELECT f1, f2 from rem1; f1 | f2 ----+-------------------- 1 | insert triggered ! (1 row) --Testcase 372: INSERT INTO rem1 values(2, 'insert'); --Testcase 373: SELECT f1, f2 from rem1; f1 | f2 ----+-------------------- 1 | insert triggered ! 2 | insert triggered ! (2 rows) --Testcase 374: UPDATE rem1 set f2 = ''; --Testcase 375: SELECT f1, f2 from rem1; f1 | f2 ----+-------------- 1 | triggered ! 2 | triggered ! (2 rows) --Testcase 376: UPDATE rem1 set f2 = 'skidoo'; --Testcase 377: SELECT f1, f2 from rem1; f1 | f2 ----+-------------------- 1 | skidoo triggered ! 2 | skidoo triggered ! (2 rows) --Testcase 669: EXPLAIN (verbose, costs off) UPDATE rem1 set f1 = 10; -- all columns should be transmitted QUERY PLAN ---------------------------------------------------------------- Update on public.rem1 -> Foreign Scan on public.rem1 Output: 10, id, rem1.* SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" (4 rows) --Testcase 670: UPDATE rem1 set f1 = 10; --Testcase 671: SELECT f1, f2 from rem1; f1 | f2 ----+-------------------------------- 10 | skidoo triggered ! triggered ! 10 | skidoo triggered ! triggered ! (2 rows) --Testcase 378: DELETE FROM rem1; -- Add a second trigger, to check that the changes are propagated correctly -- from trigger to trigger --Testcase 672: CREATE TRIGGER trig_row_before_insupd2 BEFORE INSERT OR UPDATE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); --Testcase 379: INSERT INTO rem1 values(1, 'insert'); --Testcase 380: SELECT f1, f2 from rem1; f1 | f2 ----+-------------------------------- 1 | insert triggered ! triggered ! (1 row) --Testcase 381: INSERT INTO rem1 values(2, 'insert'); --Testcase 382: SELECT f1, f2 from rem1; f1 | f2 ----+-------------------------------- 1 | insert triggered ! triggered ! 2 | insert triggered ! triggered ! (2 rows) --Testcase 383: UPDATE rem1 set f2 = ''; --Testcase 384: SELECT f1, f2 from rem1; f1 | f2 ----+-------------------------- 1 | triggered ! triggered ! 2 | triggered ! triggered ! (2 rows) --Testcase 385: UPDATE rem1 set f2 = 'skidoo'; --Testcase 386: SELECT f1, f2 from rem1; f1 | f2 ----+-------------------------------- 1 | skidoo triggered ! triggered ! 2 | skidoo triggered ! triggered ! (2 rows) --Testcase 673: DROP TRIGGER trig_row_before_insupd ON rem1; --Testcase 674: DROP TRIGGER trig_row_before_insupd2 ON rem1; --Testcase 387: DELETE from rem1; --Testcase 388: INSERT INTO rem1 VALUES (1, 'test'); -- Test with a trigger returning NULL --Testcase 675: CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$ BEGIN RETURN NULL; END $$ language plpgsql; --Testcase 676: CREATE TRIGGER trig_null BEFORE INSERT OR UPDATE OR DELETE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trig_null(); -- Nothing should have changed. --Testcase 389: INSERT INTO rem1 VALUES (2, 'test2'); --Testcase 390: SELECT f1, f2 from rem1; f1 | f2 ----+------ 1 | test (1 row) --Testcase 391: UPDATE rem1 SET f2 = 'test2'; --Testcase 392: SELECT f1, f2 from rem1; f1 | f2 ----+------ 1 | test (1 row) --Testcase 393: DELETE from rem1; --Testcase 394: SELECT f1, f2 from rem1; f1 | f2 ----+------ 1 | test (1 row) --Testcase 677: DROP TRIGGER trig_null ON rem1; --Testcase 395: DELETE from rem1; -- Test a combination of local and remote triggers --Testcase 678: CREATE TRIGGER trig_row_before BEFORE INSERT OR UPDATE OR DELETE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 679: CREATE TRIGGER trig_row_after AFTER INSERT OR UPDATE OR DELETE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 680: CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate(); --Testcase 681: INSERT INTO rem1(f2) VALUES ('test'); NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1 NOTICE: NEW: (12,"test triggered !",) NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 NOTICE: NEW: (12,"test triggered !",) --Testcase 682: UPDATE rem1 SET f2 = 'testo'; NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1 NOTICE: OLD: (12,"test triggered !",14),NEW: (12,"testo triggered !",14) NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1 NOTICE: OLD: (12,"test triggered !",14),NEW: (12,"testo triggered !",14) -- Test returning a system attribute --Testcase 683: INSERT INTO rem1(f2) VALUES ('test'); NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1 NOTICE: NEW: (13,"test triggered !",) NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1 NOTICE: NEW: (13,"test triggered !",) -- cleanup --Testcase 684: DROP TRIGGER trig_row_before ON rem1; --Testcase 685: DROP TRIGGER trig_row_after ON rem1; --Testcase 686: DROP TRIGGER trig_local_before ON rem1; -- Test direct foreign table modification functionality -- Test with statement-level triggers --Testcase 687: CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE ON rem1 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); --Testcase 396: EXPLAIN (verbose, costs off) UPDATE rem1 set f2 = ''; -- can be pushed down QUERY PLAN -------------------------------------------------------- Update on public.rem1 -> Foreign Update on public.rem1 SQLite query: UPDATE main."loc1" SET `f2` = '' (3 rows) --Testcase 397: EXPLAIN (verbose, costs off) DELETE FROM rem1; -- can be pushed down QUERY PLAN ----------------------------------------------- Delete on public.rem1 -> Foreign Delete on public.rem1 SQLite query: DELETE FROM main."loc1" (3 rows) --Testcase 688: DROP TRIGGER trig_stmt_before ON rem1; --Testcase 689: CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE ON rem1 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func(); --Testcase 398: EXPLAIN (verbose, costs off) UPDATE rem1 set f2 = ''; -- can be pushed down QUERY PLAN -------------------------------------------------------- Update on public.rem1 -> Foreign Update on public.rem1 SQLite query: UPDATE main."loc1" SET `f2` = '' (3 rows) --Testcase 399: EXPLAIN (verbose, costs off) DELETE FROM rem1; -- can be pushed down QUERY PLAN ----------------------------------------------- Delete on public.rem1 -> Foreign Delete on public.rem1 SQLite query: DELETE FROM main."loc1" (3 rows) --Testcase 690: DROP TRIGGER trig_stmt_after ON rem1; -- Test with row-level ON INSERT triggers --Testcase 691: CREATE TRIGGER trig_row_before_insert BEFORE INSERT ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 400: EXPLAIN (verbose, costs off) UPDATE rem1 set f2 = ''; -- can be pushed down QUERY PLAN -------------------------------------------------------- Update on public.rem1 -> Foreign Update on public.rem1 SQLite query: UPDATE main."loc1" SET `f2` = '' (3 rows) --Testcase 401: EXPLAIN (verbose, costs off) DELETE FROM rem1; -- can be pushed down QUERY PLAN ----------------------------------------------- Delete on public.rem1 -> Foreign Delete on public.rem1 SQLite query: DELETE FROM main."loc1" (3 rows) --Testcase 692: DROP TRIGGER trig_row_before_insert ON rem1; --Testcase 693: CREATE TRIGGER trig_row_after_insert AFTER INSERT ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 402: EXPLAIN (verbose, costs off) UPDATE rem1 set f2 = ''; -- can be pushed down QUERY PLAN -------------------------------------------------------- Update on public.rem1 -> Foreign Update on public.rem1 SQLite query: UPDATE main."loc1" SET `f2` = '' (3 rows) --Testcase 403: EXPLAIN (verbose, costs off) DELETE FROM rem1; -- can be pushed down QUERY PLAN ----------------------------------------------- Delete on public.rem1 -> Foreign Delete on public.rem1 SQLite query: DELETE FROM main."loc1" (3 rows) --Testcase 694: DROP TRIGGER trig_row_after_insert ON rem1; -- Test with row-level ON UPDATE triggers --Testcase 695: CREATE TRIGGER trig_row_before_update BEFORE UPDATE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 404: EXPLAIN (verbose, costs off) UPDATE rem1 set f2 = ''; -- can't be pushed down QUERY PLAN ---------------------------------------------------------------- Update on public.rem1 -> Foreign Scan on public.rem1 Output: ''::text, id, rem1.* SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" (4 rows) --Testcase 405: EXPLAIN (verbose, costs off) DELETE FROM rem1; -- can be pushed down QUERY PLAN ----------------------------------------------- Delete on public.rem1 -> Foreign Delete on public.rem1 SQLite query: DELETE FROM main."loc1" (3 rows) --Testcase 696: DROP TRIGGER trig_row_before_update ON rem1; --Testcase 697: CREATE TRIGGER trig_row_after_update AFTER UPDATE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 406: EXPLAIN (verbose, costs off) UPDATE rem1 set f2 = ''; -- can't be pushed down QUERY PLAN ---------------------------------------------------------------- Update on public.rem1 -> Foreign Scan on public.rem1 Output: ''::text, id, rem1.* SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" (4 rows) --Testcase 407: EXPLAIN (verbose, costs off) DELETE FROM rem1; -- can be pushed down QUERY PLAN ----------------------------------------------- Delete on public.rem1 -> Foreign Delete on public.rem1 SQLite query: DELETE FROM main."loc1" (3 rows) --Testcase 698: DROP TRIGGER trig_row_after_update ON rem1; -- Test with row-level ON DELETE triggers --Testcase 699: CREATE TRIGGER trig_row_before_delete BEFORE DELETE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 408: EXPLAIN (verbose, costs off) UPDATE rem1 set f2 = ''; -- can be pushed down QUERY PLAN -------------------------------------------------------- Update on public.rem1 -> Foreign Update on public.rem1 SQLite query: UPDATE main."loc1" SET `f2` = '' (3 rows) --Testcase 409: EXPLAIN (verbose, costs off) DELETE FROM rem1; -- can't be pushed down QUERY PLAN ---------------------------------------------------------------- Delete on public.rem1 -> Foreign Scan on public.rem1 Output: id, rem1.* SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" (4 rows) --Testcase 700: DROP TRIGGER trig_row_before_delete ON rem1; --Testcase 701: CREATE TRIGGER trig_row_after_delete AFTER DELETE ON rem1 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 410: EXPLAIN (verbose, costs off) UPDATE rem1 set f2 = ''; -- can be pushed down QUERY PLAN -------------------------------------------------------- Update on public.rem1 -> Foreign Update on public.rem1 SQLite query: UPDATE main."loc1" SET `f2` = '' (3 rows) --Testcase 411: EXPLAIN (verbose, costs off) DELETE FROM rem1; -- can't be pushed down QUERY PLAN ---------------------------------------------------------------- Delete on public.rem1 -> Foreign Scan on public.rem1 Output: id, rem1.* SQLite query: SELECT `f1`, `f2`, `id` FROM main."loc1" (4 rows) --Testcase 702: DROP TRIGGER trig_row_after_delete ON rem1; -- =================================================================== -- test inheritance features -- =================================================================== --Testcase 703: CREATE TABLE a (aa TEXT); ALTER TABLE a SET (autovacuum_enabled = 'false'); --Testcase 704: CREATE FOREIGN TABLE b (aa TEXT OPTIONS (key 'true'), bb TEXT) INHERITS (a) SERVER sqlite_svr OPTIONS (table 'loct'); NOTICE: merging column "aa" with inherited definition --Testcase 412: INSERT INTO a(aa) VALUES('aaa'); --Testcase 413: INSERT INTO a(aa) VALUES('aaaa'); --Testcase 414: INSERT INTO a(aa) VALUES('aaaaa'); --Testcase 415: INSERT INTO b(aa) VALUES('bbb'); --Testcase 416: INSERT INTO b(aa) VALUES('bbbb'); --Testcase 417: INSERT INTO b(aa) VALUES('bbbbb'); --Testcase 418: SELECT tableoid::regclass, * FROM a; tableoid | aa ----------+------- a | aaa a | aaaa a | aaaaa b | bbb b | bbbb b | bbbbb (6 rows) --Testcase 419: SELECT tableoid::regclass, * FROM b; tableoid | aa | bb ----------+-------+---- b | bbb | b | bbbb | b | bbbbb | (3 rows) --Testcase 420: SELECT tableoid::regclass, * FROM ONLY a; tableoid | aa ----------+------- a | aaa a | aaaa a | aaaaa (3 rows) --Testcase 421: UPDATE a SET aa = 'zzzzzz' WHERE aa LIKE 'aaaa%'; --Testcase 422: SELECT tableoid::regclass, * FROM a; tableoid | aa ----------+-------- a | aaa a | zzzzzz a | zzzzzz b | bbb b | bbbb b | bbbbb (6 rows) --Testcase 423: SELECT tableoid::regclass, * FROM b; tableoid | aa | bb ----------+-------+---- b | bbb | b | bbbb | b | bbbbb | (3 rows) --Testcase 424: SELECT tableoid::regclass, * FROM ONLY a; tableoid | aa ----------+-------- a | aaa a | zzzzzz a | zzzzzz (3 rows) --Testcase 425: UPDATE b SET aa = 'new'; --Testcase 426: SELECT tableoid::regclass, * FROM a; tableoid | aa ----------+-------- a | aaa a | zzzzzz a | zzzzzz b | new b | new b | new (6 rows) --Testcase 427: SELECT tableoid::regclass, * FROM b; tableoid | aa | bb ----------+-----+---- b | new | b | new | b | new | (3 rows) --Testcase 428: SELECT tableoid::regclass, * FROM ONLY a; tableoid | aa ----------+-------- a | aaa a | zzzzzz a | zzzzzz (3 rows) --Testcase 429: UPDATE a SET aa = 'newtoo'; --Testcase 430: SELECT tableoid::regclass, * FROM a; tableoid | aa ----------+-------- a | newtoo a | newtoo a | newtoo b | newtoo b | newtoo b | newtoo (6 rows) --Testcase 431: SELECT tableoid::regclass, * FROM b; tableoid | aa | bb ----------+--------+---- b | newtoo | b | newtoo | b | newtoo | (3 rows) --Testcase 432: SELECT tableoid::regclass, * FROM ONLY a; tableoid | aa ----------+-------- a | newtoo a | newtoo a | newtoo (3 rows) --Testcase 433: DELETE FROM a; --Testcase 434: SELECT tableoid::regclass, * FROM a; tableoid | aa ----------+---- (0 rows) --Testcase 435: SELECT tableoid::regclass, * FROM b; tableoid | aa | bb ----------+----+---- (0 rows) --Testcase 436: SELECT tableoid::regclass, * FROM ONLY a; tableoid | aa ----------+---- (0 rows) --Testcase 705: DROP TABLE a CASCADE; NOTICE: drop cascades to foreign table b -- Check SELECT FOR UPDATE/SHARE with an inherited source table --Testcase 706: create table foo (f1 int, f2 int); --Testcase 707: create foreign table foo2 (f3 int OPTIONS (key 'true')) inherits (foo) server sqlite_svr options (table 'loct1'); --Testcase 708: create table bar (f1 int, f2 int); --Testcase 709: create foreign table bar2 (f3 int OPTIONS (key 'true')) inherits (bar) server sqlite_svr options (table 'loct2'); alter table foo set (autovacuum_enabled = 'false'); alter table bar set (autovacuum_enabled = 'false'); --Testcase 437: insert into foo values(1,1); --Testcase 438: insert into foo values(3,3); --Testcase 439: insert into foo2 values(2,2,2); --Testcase 440: insert into foo2 values(4,4,4); --Testcase 441: insert into bar values(1,11); --Testcase 442: insert into bar values(2,22); --Testcase 443: insert into bar values(6,66); --Testcase 444: insert into bar2 values(3,33,33); --Testcase 445: insert into bar2 values(4,44,44); --Testcase 446: insert into bar2 values(7,77,77); --Testcase 447: explain (verbose, costs off) select * from bar where f1 in (select f1 from foo) for update; QUERY PLAN ---------------------------------------------------------------------------------------------- LockRows Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid -> Hash Join Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid Inner Unique: true Hash Cond: (bar.f1 = foo.f1) -> Append -> Seq Scan on public.bar bar_1 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid -> Foreign Scan on public.bar2 bar_2 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" -> Hash Output: foo.ctid, foo.f1, foo.*, foo.tableoid -> HashAggregate Output: foo.ctid, foo.f1, foo.*, foo.tableoid Group Key: foo.f1 -> Append -> Seq Scan on public.foo foo_1 Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid -> Foreign Scan on public.foo2 foo_2 Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" (23 rows) --Testcase 448: select * from bar where f1 in (select f1 from foo) for update; f1 | f2 ----+---- 1 | 11 2 | 22 3 | 33 4 | 44 (4 rows) --Testcase 449: explain (verbose, costs off) select * from bar where f1 in (select f1 from foo) for share; QUERY PLAN ---------------------------------------------------------------------------------------------- LockRows Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid -> Hash Join Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid Inner Unique: true Hash Cond: (bar.f1 = foo.f1) -> Append -> Seq Scan on public.bar bar_1 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid -> Foreign Scan on public.bar2 bar_2 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" -> Hash Output: foo.ctid, foo.f1, foo.*, foo.tableoid -> HashAggregate Output: foo.ctid, foo.f1, foo.*, foo.tableoid Group Key: foo.f1 -> Append -> Seq Scan on public.foo foo_1 Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid -> Foreign Scan on public.foo2 foo_2 Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" (23 rows) --Testcase 450: select * from bar where f1 in (select f1 from foo) for share; f1 | f2 ----+---- 1 | 11 2 | 22 3 | 33 4 | 44 (4 rows) -- Now check SELECT FOR UPDATE/SHARE with an inherited source table, -- where the parent is itself a foreign table create foreign table foo2child (f3 int) inherits (foo2) server sqlite_svr options (table 'loct4_2'); NOTICE: moving and merging column "f3" with inherited definition DETAIL: User-specified column moved to the position of the inherited column. explain (verbose, costs off) select * from bar where f1 in (select f1 from foo2) for share; QUERY PLAN ------------------------------------------------------------------------------------------- LockRows Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.tableoid -> Hash Join Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.tableoid Inner Unique: true Hash Cond: (bar.f1 = foo2.f1) -> Append -> Seq Scan on public.bar bar_1 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid -> Foreign Scan on public.bar2 bar_2 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" -> Hash Output: foo2.*, foo2.f1, foo2.tableoid -> HashAggregate Output: foo2.*, foo2.f1, foo2.tableoid Group Key: foo2.f1 -> Append -> Foreign Scan on public.foo2 foo2_1 Output: foo2_1.*, foo2_1.f1, foo2_1.tableoid SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" -> Foreign Scan on public.foo2child foo2_2 Output: foo2_2.*, foo2_2.f1, foo2_2.tableoid SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct4_2" (24 rows) select * from bar where f1 in (select f1 from foo2) for share; f1 | f2 ----+---- 2 | 22 4 | 44 (2 rows) drop foreign table foo2child; -- And with a local child relation of the foreign table parent create table foo2child (f3 int) inherits (foo2); NOTICE: moving and merging column "f3" with inherited definition DETAIL: User-specified column moved to the position of the inherited column. explain (verbose, costs off) select * from bar where f1 in (select f1 from foo2) for share; QUERY PLAN ------------------------------------------------------------------------------------------------- LockRows Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.ctid, foo2.tableoid -> Hash Join Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.ctid, foo2.tableoid Inner Unique: true Hash Cond: (bar.f1 = foo2.f1) -> Append -> Seq Scan on public.bar bar_1 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid -> Foreign Scan on public.bar2 bar_2 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" -> Hash Output: foo2.*, foo2.f1, foo2.ctid, foo2.tableoid -> HashAggregate Output: foo2.*, foo2.f1, foo2.ctid, foo2.tableoid Group Key: foo2.f1 -> Append -> Foreign Scan on public.foo2 foo2_1 Output: foo2_1.*, foo2_1.f1, foo2_1.ctid, foo2_1.tableoid SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" -> Seq Scan on public.foo2child foo2_2 Output: foo2_2.*, foo2_2.f1, foo2_2.ctid, foo2_2.tableoid (23 rows) select * from bar where f1 in (select f1 from foo2) for share; f1 | f2 ----+---- 2 | 22 4 | 44 (2 rows) drop table foo2child; -- Check UPDATE with inherited target and an inherited source table --Testcase 451: explain (verbose, costs off) update bar set f2 = f2 + 100 where f1 in (select f1 from foo); QUERY PLAN ------------------------------------------------------------------------------------------------------------------------ Update on public.bar Update on public.bar bar_1 Foreign Update on public.bar2 bar_2 -> Hash Join Output: (bar.f2 + 100), foo.ctid, bar.tableoid, bar.ctid, (NULL::integer), (NULL::record), foo.*, foo.tableoid Inner Unique: true Hash Cond: (bar.f1 = foo.f1) -> Append -> Seq Scan on public.bar bar_1 Output: bar_1.f2, bar_1.f1, bar_1.tableoid, bar_1.ctid, NULL::integer, NULL::record -> Foreign Scan on public.bar2 bar_2 Output: bar_2.f2, bar_2.f1, bar_2.tableoid, NULL::tid, bar_2.f3, bar_2.* SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" -> Hash Output: foo.ctid, foo.f1, foo.*, foo.tableoid -> HashAggregate Output: foo.ctid, foo.f1, foo.*, foo.tableoid Group Key: foo.f1 -> Append -> Seq Scan on public.foo foo_1 Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid -> Foreign Scan on public.foo2 foo_2 Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct1" (24 rows) --Testcase 452: update bar set f2 = f2 + 100 where f1 in (select f1 from foo); --Testcase 453: select tableoid::regclass, * from bar order by 1,2; tableoid | f1 | f2 ----------+----+----- bar | 1 | 111 bar | 2 | 122 bar | 6 | 66 bar2 | 3 | 133 bar2 | 4 | 144 bar2 | 7 | 77 (6 rows) -- Check UPDATE with inherited target and an appendrel subquery --Testcase 454: explain (verbose, costs off) update bar set f2 = f2 + 100 from ( select f1 from foo union all select f1+3 from foo ) ss where bar.f1 = ss.f1; QUERY PLAN --------------------------------------------------------------------------------------------------------------- Update on public.bar Update on public.bar bar_1 Foreign Update on public.bar2 bar_2 -> Merge Join Output: (bar.f2 + 100), (ROW(foo.f1)), bar.tableoid, bar.ctid, (NULL::integer), (NULL::record) Merge Cond: (bar.f1 = foo.f1) -> Sort Output: bar.f2, bar.f1, bar.tableoid, bar.ctid, (NULL::integer), (NULL::record) Sort Key: bar.f1 -> Append -> Seq Scan on public.bar bar_1 Output: bar_1.f2, bar_1.f1, bar_1.tableoid, bar_1.ctid, NULL::integer, NULL::record -> Foreign Scan on public.bar2 bar_2 Output: bar_2.f2, bar_2.f1, bar_2.tableoid, NULL::tid, bar_2.f3, bar_2.* SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" -> Sort Output: (ROW(foo.f1)), foo.f1 Sort Key: foo.f1 -> Append -> Seq Scan on public.foo Output: ROW(foo.f1), foo.f1 -> Foreign Scan on public.foo2 foo_1 Output: ROW(foo_1.f1), foo_1.f1 SQLite query: SELECT `f1` FROM main."loct1" -> Seq Scan on public.foo foo_2 Output: ROW((foo_2.f1 + 3)), (foo_2.f1 + 3) -> Foreign Scan on public.foo2 foo_3 Output: ROW((foo_3.f1 + 3)), (foo_3.f1 + 3) SQLite query: SELECT `f1` FROM main."loct1" (29 rows) --Testcase 455: update bar set f2 = f2 + 100 from ( select f1 from foo union all select f1+3 from foo ) ss where bar.f1 = ss.f1; --Testcase 456: select tableoid::regclass, * from bar order by 1,2; tableoid | f1 | f2 ----------+----+----- bar | 1 | 211 bar | 2 | 222 bar | 6 | 166 bar2 | 3 | 233 bar2 | 4 | 244 bar2 | 7 | 177 (6 rows) -- Test forcing the remote server to produce sorted data for a merge join, -- but the foreign table is an inheritance child. --truncate table loct1; --Testcase 710: delete from foo2; truncate table only foo; \set num_rows_foo 2000 --Testcase 711: insert into foo2 select generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2); --Testcase 712: insert into foo select generate_series(1, :num_rows_foo, 2), generate_series(1, :num_rows_foo, 2); SET enable_hashjoin to false; SET enable_nestloop to false; --alter foreign table foo2 options (use_remote_estimate 'true'); --create index i_loct1_f1 on loct1(f1); --Testcase 713: create index i_foo_f1 on foo(f1); analyze foo; --analyze loct1; -- inner join; expressions in the clauses appear in the equivalence class list --Testcase 714: explain (verbose, costs off) select foo.f1, foo2.f1 from foo join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; QUERY PLAN ---------------------------------------------------------------------------------------------------------------- Limit Output: foo.f1, foo2.f1, foo.f2 -> Sort Output: foo.f1, foo2.f1, foo.f2 Sort Key: foo.f2 -> Merge Join Output: foo.f1, foo2.f1, foo.f2 Merge Cond: (foo.f1 = foo2.f1) -> Sort Output: foo.f1, foo.f2 Sort Key: foo.f1 -> Append -> Seq Scan on public.foo foo_1 Output: foo_1.f1, foo_1.f2 -> Foreign Scan on public.foo2 foo_2 Output: foo_2.f1, foo_2.f2 SQLite query: SELECT `f1`, `f2` FROM main."loct1" ORDER BY `f2` ASC NULLS LAST -> Sort Output: foo2.f1 Sort Key: foo2.f1 -> Foreign Scan on public.foo2 Output: foo2.f1 SQLite query: SELECT `f1` FROM main."loct1" (23 rows) --Testcase 715: select foo.f1, foo2.f1 from foo join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; f1 | f1 ----+---- 20 | 20 22 | 22 24 | 24 26 | 26 28 | 28 30 | 30 32 | 32 34 | 34 36 | 36 38 | 38 (10 rows) -- outer join; expressions in the clauses do not appear in equivalence class -- list but no output change as compared to the previous query --Testcase 716: explain (verbose, costs off) select foo.f1, foo2.f1 from foo left join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; QUERY PLAN ---------------------------------------------------------------------------------------------------------------- Limit Output: foo.f1, foo2.f1, foo.f2 -> Sort Output: foo.f1, foo2.f1, foo.f2 Sort Key: foo.f2 -> Merge Left Join Output: foo.f1, foo2.f1, foo.f2 Merge Cond: (foo.f1 = foo2.f1) -> Sort Output: foo.f1, foo.f2 Sort Key: foo.f1 -> Append -> Seq Scan on public.foo foo_1 Output: foo_1.f1, foo_1.f2 -> Foreign Scan on public.foo2 foo_2 Output: foo_2.f1, foo_2.f2 SQLite query: SELECT `f1`, `f2` FROM main."loct1" ORDER BY `f2` ASC NULLS LAST -> Sort Output: foo2.f1 Sort Key: foo2.f1 -> Foreign Scan on public.foo2 Output: foo2.f1 SQLite query: SELECT `f1` FROM main."loct1" (23 rows) --Testcase 717: select foo.f1, foo2.f1 from foo left join foo2 on (foo.f1 = foo2.f1) order by foo.f2 offset 10 limit 10; f1 | f1 ----+---- 10 | 10 11 | 12 | 12 13 | 14 | 14 15 | 16 | 16 17 | 18 | 18 19 | (10 rows) RESET enable_hashjoin; RESET enable_nestloop; -- Test that WHERE CURRENT OF is not supported begin; declare c cursor for select * from bar where f1 = 7; --Testcase 457: fetch from c; f1 | f2 ----+----- 7 | 177 (1 row) --Testcase 458: update bar set f2 = null where current of c; ERROR: WHERE CURRENT OF is not supported for this table type rollback; --Testcase 459: explain (verbose, costs off) delete from foo where f1 < 5; QUERY PLAN ------------------------------------------------------------------------- Delete on public.foo Delete on public.foo foo_1 Foreign Delete on public.foo2 foo_2 -> Append -> Index Scan using i_foo_f1 on public.foo foo_1 Output: foo_1.tableoid, foo_1.ctid, NULL::integer Index Cond: (foo_1.f1 < 5) -> Foreign Delete on public.foo2 foo_2 SQLite query: DELETE FROM main."loct1" WHERE ((`f1` < 5)) (9 rows) --Testcase 460: delete from foo where f1 < 5; --Testcase 461: explain (verbose, costs off) update bar set f2 = f2 + 100; QUERY PLAN ----------------------------------------------------------------------------------------------- Update on public.bar Update on public.bar bar_1 Foreign Update on public.bar2 bar_2 -> Result Output: (bar.f2 + 100), bar.tableoid, bar.ctid, (NULL::integer), (NULL::record) -> Append -> Seq Scan on public.bar bar_1 Output: bar_1.f2, bar_1.tableoid, bar_1.ctid, NULL::integer, NULL::record -> Foreign Update on public.bar2 bar_2 SQLite query: UPDATE main."loct2" SET `f2` = (`f2` + 100) (10 rows) --Testcase 462: update bar set f2 = f2 + 100; --Testcase 463: select * from bar; f1 | f2 ----+----- 1 | 311 2 | 322 6 | 266 3 | 333 4 | 344 7 | 277 (6 rows) -- Test that UPDATE/DELETE with inherited target works with row-level triggers --Testcase 718: CREATE TRIGGER trig_row_before BEFORE UPDATE OR DELETE ON bar2 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 719: CREATE TRIGGER trig_row_after AFTER UPDATE OR DELETE ON bar2 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo'); --Testcase 464: explain (verbose, costs off) update bar set f2 = f2 + 100; QUERY PLAN ----------------------------------------------------------------------------------------------- Update on public.bar Update on public.bar bar_1 Foreign Update on public.bar2 bar_2 -> Result Output: (bar.f2 + 100), bar.tableoid, bar.ctid, (NULL::integer), (NULL::record) -> Append -> Seq Scan on public.bar bar_1 Output: bar_1.f2, bar_1.tableoid, bar_1.ctid, NULL::integer, NULL::record -> Foreign Scan on public.bar2 bar_2 Output: bar_2.f2, bar_2.tableoid, NULL::tid, bar_2.f3, bar_2.* SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" (11 rows) --Testcase 465: update bar set f2 = f2 + 100; NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2 NOTICE: OLD: (3,333,33),NEW: (3,433,33) NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2 NOTICE: OLD: (4,344,44),NEW: (4,444,44) NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2 NOTICE: OLD: (7,277,77),NEW: (7,377,77) NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2 NOTICE: OLD: (3,333,33),NEW: (3,433,33) NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2 NOTICE: OLD: (4,344,44),NEW: (4,444,44) NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2 NOTICE: OLD: (7,277,77),NEW: (7,377,77) --Testcase 466: explain (verbose, costs off) delete from bar where f2 < 400; QUERY PLAN -------------------------------------------------------------------------------------------- Delete on public.bar Delete on public.bar bar_1 Foreign Delete on public.bar2 bar_2 -> Append -> Seq Scan on public.bar bar_1 Output: bar_1.tableoid, bar_1.ctid, NULL::integer, NULL::record Filter: (bar_1.f2 < 400) -> Foreign Scan on public.bar2 bar_2 Output: bar_2.tableoid, NULL::tid, bar_2.f3, bar_2.* SQLite query: SELECT `f1`, `f2`, `f3` FROM main."loct2" WHERE ((`f2` < 400)) (10 rows) --Testcase 467: delete from bar where f2 < 400; NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON bar2 NOTICE: OLD: (7,377,77) NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON bar2 NOTICE: OLD: (7,377,77) -- cleanup --Testcase 720: drop table foo cascade; NOTICE: drop cascades to foreign table foo2 --Testcase 721: drop table bar cascade; NOTICE: drop cascades to foreign table bar2 -- Test pushing down UPDATE/DELETE joins to the remote server --Testcase 722: create table parent (a int, b text); --Testcase 723: create foreign table remt1 (a int OPTIONS (key 'true'), b text) server sqlite_svr options (table 'loct3'); --Testcase 724: create foreign table remt2 (a int OPTIONS (key 'true'), b text) server sqlite_svr options (table 'loct4'); alter foreign table remt1 inherit parent; --Testcase 468: insert into remt1 values (1, 'foo'); --Testcase 469: insert into remt1 values (2, 'bar'); --Testcase 470: insert into remt2 values (1, 'foo'); --Testcase 471: insert into remt2 values (2, 'bar'); --Testcase 472: explain (verbose, costs off) update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a; QUERY PLAN ------------------------------------------------------------------------------------------------------------------------- Update on public.parent Update on public.parent parent_1 Foreign Update on public.remt1 parent_2 -> Hash Join Output: (parent.b || remt2.b), remt2.*, parent.tableoid, parent.ctid, (NULL::integer), (NULL::record) Hash Cond: (remt2.a = parent.a) -> Foreign Scan on public.remt2 Output: remt2.b, remt2.*, remt2.a SQLite query: SELECT `a`, `b` FROM main."loct4" -> Hash Output: parent.b, parent.a, parent.tableoid, parent.ctid, (NULL::integer), (NULL::record) -> Append -> Seq Scan on public.parent parent_1 Output: parent_1.b, parent_1.a, parent_1.tableoid, parent_1.ctid, NULL::integer, NULL::record -> Foreign Scan on public.remt1 parent_2 Output: parent_2.b, parent_2.a, parent_2.tableoid, NULL::tid, parent_2.a, parent_2.* SQLite query: SELECT `a`, `b` FROM main."loct3" (17 rows) --Testcase 473: update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a; --Testcase 474: select * from parent inner join remt2 on (parent.a = remt2.a); a | b | a | b ---+--------+---+----- 1 | foofoo | 1 | foo 2 | barbar | 2 | bar (2 rows) --Testcase 475: explain (verbose, costs off) delete from parent using remt2 where parent.a = remt2.a; QUERY PLAN ----------------------------------------------------------------------------------------------- Delete on public.parent Delete on public.parent parent_1 Foreign Delete on public.remt1 parent_2 -> Merge Join Output: remt2.*, parent.tableoid, parent.ctid, (NULL::integer) Merge Cond: (remt2.a = parent.a) -> Sort Output: remt2.*, remt2.a Sort Key: remt2.a -> Foreign Scan on public.remt2 Output: remt2.*, remt2.a SQLite query: SELECT `a`, `b` FROM main."loct4" -> Sort Output: parent.a, parent.tableoid, parent.ctid, (NULL::integer) Sort Key: parent.a -> Append -> Seq Scan on public.parent parent_1 Output: parent_1.a, parent_1.tableoid, parent_1.ctid, NULL::integer -> Foreign Scan on public.remt1 parent_2 Output: parent_2.a, parent_2.tableoid, NULL::tid, parent_2.a SQLite query: SELECT `a` FROM main."loct3" (21 rows) --Testcase 476: delete from parent using remt2 where parent.a = remt2.a; -- cleanup --Testcase 725: drop foreign table remt1; --Testcase 726: drop foreign table remt2; --Testcase 727: drop table parent; /* -- Skip these tests, sqlite fdw does not support partition table, check constraint, copy from -- =================================================================== -- test tuple routing for foreign-table partitions -- =================================================================== -- Test insert tuple routing create table itrtest (a int, b text) partition by list (a); create table loct1 (a int check (a in (1)), b text); create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1'); create table loct2 (a int check (a in (2)), b text); create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2'); alter table itrtest attach partition remp1 for values in (1); alter table itrtest attach partition remp2 for values in (2); insert into itrtest values (1, 'foo'); insert into itrtest values (1, 'bar') returning *; insert into itrtest values (2, 'baz'); insert into itrtest values (2, 'qux') returning *; insert into itrtest values (1, 'test1'), (2, 'test2') returning *; select tableoid::regclass, * FROM itrtest; select tableoid::regclass, * FROM remp1; select tableoid::regclass, * FROM remp2; delete from itrtest; create unique index loct1_idx on loct1 (a); -- DO NOTHING without an inference specification is supported insert into itrtest values (1, 'foo') on conflict do nothing returning *; insert into itrtest values (1, 'foo') on conflict do nothing returning *; -- But other cases are not supported insert into itrtest values (1, 'bar') on conflict (a) do nothing; insert into itrtest values (1, 'bar') on conflict (a) do update set b = excluded.b; select tableoid::regclass, * FROM itrtest; delete from itrtest; drop index loct1_idx; -- Test that remote triggers work with insert tuple routing create function br_insert_trigfunc() returns trigger as $$ begin new.b := new.b || ' triggered !'; return new; end $$ language plpgsql; create trigger loct1_br_insert_trigger before insert on loct1 for each row execute procedure br_insert_trigfunc(); create trigger loct2_br_insert_trigger before insert on loct2 for each row execute procedure br_insert_trigfunc(); -- The new values are concatenated with ' triggered !' insert into itrtest values (1, 'foo') returning *; insert into itrtest values (2, 'qux') returning *; insert into itrtest values (1, 'test1'), (2, 'test2') returning *; with result as (insert into itrtest values (1, 'test1'), (2, 'test2') returning *) select * from result; drop trigger loct1_br_insert_trigger on loct1; drop trigger loct2_br_insert_trigger on loct2; drop table itrtest; drop table loct1; drop table loct2; -- Test update tuple routing create table utrtest (a int, b text) partition by list (a); create table loct (a int check (a in (1)), b text); create foreign table remp (a int check (a in (1)), b text) server loopback options (table_name 'loct'); create table locp (a int check (a in (2)), b text); alter table utrtest attach partition remp for values in (1); alter table utrtest attach partition locp for values in (2); insert into utrtest values (1, 'foo'); insert into utrtest values (2, 'qux'); select tableoid::regclass, * FROM utrtest; select tableoid::regclass, * FROM remp; select tableoid::regclass, * FROM locp; -- It's not allowed to move a row from a partition that is foreign to another update utrtest set a = 2 where b = 'foo' returning *; -- But the reverse is allowed update utrtest set a = 1 where b = 'qux' returning *; select tableoid::regclass, * FROM utrtest; select tableoid::regclass, * FROM remp; select tableoid::regclass, * FROM locp; -- The executor should not let unexercised FDWs shut down update utrtest set a = 1 where b = 'foo'; -- Test that remote triggers work with update tuple routing create trigger loct_br_insert_trigger before insert on loct for each row execute procedure br_insert_trigfunc(); delete from utrtest; insert into utrtest values (2, 'qux'); -- Check case where the foreign partition is a subplan target rel explain (verbose, costs off) update utrtest set a = 1 where a = 1 or a = 2 returning *; -- The new values are concatenated with ' triggered !' update utrtest set a = 1 where a = 1 or a = 2 returning *; delete from utrtest; insert into utrtest values (2, 'qux'); -- Check case where the foreign partition isn't a subplan target rel explain (verbose, costs off) update utrtest set a = 1 where a = 2 returning *; -- The new values are concatenated with ' triggered !' update utrtest set a = 1 where a = 2 returning *; drop trigger loct_br_insert_trigger on loct; -- We can move rows to a foreign partition that has been updated already, -- but can't move rows to a foreign partition that hasn't been updated yet delete from utrtest; insert into utrtest values (1, 'foo'); insert into utrtest values (2, 'qux'); -- Test the former case: -- with a direct modification plan explain (verbose, costs off) update utrtest set a = 1 returning *; update utrtest set a = 1 returning *; delete from utrtest; insert into utrtest values (1, 'foo'); insert into utrtest values (2, 'qux'); -- with a non-direct modification plan explain (verbose, costs off) update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *; update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *; -- Change the definition of utrtest so that the foreign partition get updated -- after the local partition delete from utrtest; alter table utrtest detach partition remp; drop foreign table remp; alter table loct drop constraint loct_a_check; alter table loct add check (a in (3)); create foreign table remp (a int check (a in (3)), b text) server loopback options (table_name 'loct'); alter table utrtest attach partition remp for values in (3); insert into utrtest values (2, 'qux'); insert into utrtest values (3, 'xyzzy'); -- Test the latter case: -- with a direct modification plan explain (verbose, costs off) update utrtest set a = 3 returning *; update utrtest set a = 3 returning *; -- ERROR -- with a non-direct modification plan explain (verbose, costs off) update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; -- ERROR drop table utrtest; drop table loct; -- Test copy tuple routing create table ctrtest (a int, b text) partition by list (a); create table loct1 (a int check (a in (1)), b text); create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1'); create table loct2 (a int check (a in (2)), b text); create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2'); alter table ctrtest attach partition remp1 for values in (1); alter table ctrtest attach partition remp2 for values in (2); copy ctrtest from stdin; 1 foo 2 qux \. select tableoid::regclass, * FROM ctrtest; select tableoid::regclass, * FROM remp1; select tableoid::regclass, * FROM remp2; -- Copying into foreign partitions directly should work as well copy remp1 from stdin; 1 bar \. select tableoid::regclass, * FROM remp1; drop table ctrtest; drop table loct1; drop table loct2; -- =================================================================== -- test COPY FROM -- =================================================================== create table loc2 (f1 int, f2 text); alter table loc2 set (autovacuum_enabled = 'false'); create foreign table rem2 (f1 int, f2 text) server loopback options(table_name 'loc2'); -- Test basic functionality copy rem2 from stdin; 1 foo 2 bar \. select * from rem2; delete from rem2; -- Test check constraints alter table loc2 add constraint loc2_f1positive check (f1 >= 0); alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0); -- check constraint is enforced on the remote side, not locally copy rem2 from stdin; 1 foo 2 bar \. copy rem2 from stdin; -- ERROR -1 xyzzy \. select * from rem2; alter foreign table rem2 drop constraint rem2_f1positive; alter table loc2 drop constraint loc2_f1positive; delete from rem2; -- Test local triggers create trigger trig_stmt_before before insert on rem2 for each statement execute procedure trigger_func(); create trigger trig_stmt_after after insert on rem2 for each statement execute procedure trigger_func(); create trigger trig_row_before before insert on rem2 for each row execute procedure trigger_data(23,'skidoo'); create trigger trig_row_after after insert on rem2 for each row execute procedure trigger_data(23,'skidoo'); copy rem2 from stdin; 1 foo 2 bar \. select * from rem2; drop trigger trig_row_before on rem2; drop trigger trig_row_after on rem2; drop trigger trig_stmt_before on rem2; drop trigger trig_stmt_after on rem2; delete from rem2; create trigger trig_row_before_insert before insert on rem2 for each row execute procedure trig_row_before_insupdate(); -- The new values are concatenated with ' triggered !' copy rem2 from stdin; 1 foo 2 bar \. select * from rem2; drop trigger trig_row_before_insert on rem2; delete from rem2; create trigger trig_null before insert on rem2 for each row execute procedure trig_null(); -- Nothing happens copy rem2 from stdin; 1 foo 2 bar \. select * from rem2; drop trigger trig_null on rem2; delete from rem2; -- Test remote triggers create trigger trig_row_before_insert before insert on loc2 for each row execute procedure trig_row_before_insupdate(); -- The new values are concatenated with ' triggered !' copy rem2 from stdin; 1 foo 2 bar \. select * from rem2; drop trigger trig_row_before_insert on loc2; delete from rem2; create trigger trig_null before insert on loc2 for each row execute procedure trig_null(); -- Nothing happens copy rem2 from stdin; 1 foo 2 bar \. select * from rem2; drop trigger trig_null on loc2; delete from rem2; -- Test a combination of local and remote triggers create trigger rem2_trig_row_before before insert on rem2 for each row execute procedure trigger_data(23,'skidoo'); create trigger rem2_trig_row_after after insert on rem2 for each row execute procedure trigger_data(23,'skidoo'); create trigger loc2_trig_row_before_insert before insert on loc2 for each row execute procedure trig_row_before_insupdate(); copy rem2 from stdin; 1 foo 2 bar \. select * from rem2; drop trigger rem2_trig_row_before on rem2; drop trigger rem2_trig_row_after on rem2; drop trigger loc2_trig_row_before_insert on loc2; delete from rem2; -- test COPY FROM with foreign table created in the same transaction create table loc3 (f1 int, f2 text); begin; create foreign table rem3 (f1 int, f2 text) server loopback options(table_name 'loc3'); copy rem3 from stdin; 1 foo 2 bar \. commit; select * from rem3; drop foreign table rem3; drop table loc3; */ -- =================================================================== -- test for TRUNCATE -- =================================================================== CREATE FOREIGN TABLE tru_ftable (id int) SERVER sqlite_svr OPTIONS (table 'tru_rtable0'); INSERT INTO "S 1".tru_rtable0 (SELECT x FROM generate_series(1,10) x); -- CREATE TABLE tru_ptable (id int) PARTITION BY HASH(id); -- CREATE TABLE tru_ptable__p0 PARTITION OF tru_ptable -- FOR VALUES WITH (MODULUS 2, REMAINDER 0); -- CREATE TABLE tru_rtable1 (id int primary key); -- CREATE FOREIGN TABLE tru_ftable__p1 (id int) -- SERVER sqlite_svr OPTIONS (table 'tru_ptable'); -- INSERT INTO tru_ptable (SELECT x FROM generate_series(11,20) x); INSERT INTO "S 1".tru_pk_table (SELECT x FROM generate_series(1,10) x); INSERT INTO "S 1".tru_fk_table(fkey) (SELECT x % 10 + 1 FROM generate_series(5,25) x); CREATE FOREIGN TABLE tru_pk_ftable (id int) SERVER sqlite_svr OPTIONS (table 'tru_pk_table'); CREATE FOREIGN TABLE tru_ftable_parent (id int) SERVER sqlite_svr OPTIONS (table 'tru_rtable_parent'); CREATE FOREIGN TABLE tru_ftable_child () INHERITS (tru_ftable_parent) SERVER sqlite_svr OPTIONS (table 'tru_rtable_child'); INSERT INTO "S 1".tru_rtable_parent (SELECT x FROM generate_series(1,8) x); INSERT INTO "S 1".tru_rtable_child (SELECT x FROM generate_series(10, 18) x); -- normal truncate SELECT sum(id) FROM tru_ftable; -- 55 sum ----- 55 (1 row) TRUNCATE tru_ftable; SELECT count(*) FROM "S 1".tru_rtable0; -- 0 count ------- 0 (1 row) SELECT count(*) FROM tru_ftable; -- 0 count ------- 0 (1 row) -- 'truncatable' option ALTER SERVER sqlite_svr OPTIONS (ADD truncatable 'false'); TRUNCATE tru_ftable; -- error ERROR: foreign table "tru_ftable" does not allow truncates ALTER FOREIGN TABLE tru_ftable OPTIONS (ADD truncatable 'true'); TRUNCATE tru_ftable; -- accepted ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'false'); TRUNCATE tru_ftable; -- error ERROR: foreign table "tru_ftable" does not allow truncates ALTER SERVER sqlite_svr OPTIONS (DROP truncatable); ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'false'); TRUNCATE tru_ftable; -- error ERROR: foreign table "tru_ftable" does not allow truncates ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'true'); TRUNCATE tru_ftable; -- accepted -- -- partitioned table with both local and foreign tables as partitions -- SELECT sum(id) FROM tru_ptable; -- 155 -- TRUNCATE tru_ptable; -- SELECT count(*) FROM tru_ptable; -- 0 -- SELECT count(*) FROM tru_ptable__p0; -- 0 -- SELECT count(*) FROM tru_ftable__p1; -- 0 -- SELECT count(*) FROM tru_rtable1; -- 0 -- 'CASCADE' option SELECT sum(id) FROM tru_pk_ftable; -- 55 sum ----- 55 (1 row) -- SQLite FDW support TRUNCATE command by executing DELETE statement without WHERE clause. -- In order to delete records in parent and child table subsequently, -- SQLite FDW executes "PRAGMA foreign_keys = ON" before executing DELETE statement. TRUNCATE tru_pk_ftable; -- success TRUNCATE tru_pk_ftable CASCADE; -- success SELECT count(*) FROM tru_pk_ftable; -- 0 count ------- 0 (1 row) SELECT count(*) FROM "S 1".tru_fk_table; -- also truncated,0 count ------- 0 (1 row) -- truncate two tables at a command INSERT INTO tru_ftable (SELECT x FROM generate_series(1,8) x); INSERT INTO tru_pk_ftable (SELECT x FROM generate_series(3,10) x); SELECT count(*) from tru_ftable; -- 8 count ------- 8 (1 row) SELECT count(*) from tru_pk_ftable; -- 8 count ------- 8 (1 row) TRUNCATE tru_ftable, tru_pk_ftable; SELECT count(*) from tru_ftable; -- 0 count ------- 0 (1 row) SELECT count(*) from tru_pk_ftable; -- 0 count ------- 0 (1 row) -- truncate with ONLY clause -- Since ONLY is specified, the table tru_ftable_child that inherits -- tru_ftable_parent locally is not truncated. TRUNCATE ONLY tru_ftable_parent; SELECT sum(id) FROM tru_ftable_parent; -- 126 sum ----- 126 (1 row) TRUNCATE tru_ftable_parent; SELECT count(*) FROM tru_ftable_parent; -- 0 count ------- 0 (1 row) -- -- in case when remote table has inherited children -- CREATE TABLE tru_rtable0_child () INHERITS (tru_rtable0); -- INSERT INTO tru_rtable0 (SELECT x FROM generate_series(5,9) x); -- INSERT INTO "S 1".tru_rtable0_child (SELECT x FROM generate_series(10,14) x); -- SELECT sum(id) FROM tru_ftable; -- 95 -- -- Both parent and child tables in the foreign server are truncated -- -- even though ONLY is specified because ONLY has no effect -- -- when truncating a foreign table. -- TRUNCATE ONLY tru_ftable; -- SELECT count(*) FROM tru_ftable; -- 0 -- INSERT INTO tru_rtable0 (SELECT x FROM generate_series(21,25) x); -- INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(26,30) x); -- SELECT sum(id) FROM tru_ftable; -- 255 -- TRUNCATE tru_ftable; -- truncate both of parent and child -- SELECT count(*) FROM tru_ftable; -- 0 -- cleanup DROP FOREIGN TABLE tru_ftable_parent, tru_ftable_child, tru_pk_ftable,tru_ftable; -- DROP TABLE tru_rtable0, tru_rtable1, tru_ptable, tru_ptable__p0, tru_pk_table, tru_fk_table, -- tru_rtable_parent,tru_rtable_child, tru_rtable0_child; -- =================================================================== -- test IMPORT FOREIGN SCHEMA -- =================================================================== --Testcase 728: CREATE SCHEMA import_dest1; IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest1; --Testcase 477: \det+ import_dest1.* List of foreign tables Schema | Table | Server | FDW options | Description --------------+-------------------+------------+-------------------------------+------------- import_dest1 | T 0 | sqlite_svr | ("table" 'T 0') | import_dest1 | T 1 | sqlite_svr | ("table" 'T 1') | import_dest1 | T 2 | sqlite_svr | ("table" 'T 2') | import_dest1 | T 3 | sqlite_svr | ("table" 'T 3') | import_dest1 | T 4 | sqlite_svr | ("table" 'T 4') | import_dest1 | base_tbl | sqlite_svr | ("table" 'base_tbl') | import_dest1 | batch_table | sqlite_svr | ("table" 'batch_table') | import_dest1 | foreign_tbl | sqlite_svr | ("table" 'foreign_tbl') | import_dest1 | ft3 | sqlite_svr | ("table" 'ft3') | import_dest1 | grem1 | sqlite_svr | ("table" 'grem1') | import_dest1 | loc1 | sqlite_svr | ("table" 'loc1') | import_dest1 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest1 | loct | sqlite_svr | ("table" 'loct') | import_dest1 | loct1 | sqlite_svr | ("table" 'loct1') | import_dest1 | loct2 | sqlite_svr | ("table" 'loct2') | import_dest1 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest1 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest1 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | import_dest1 | loct5 | sqlite_svr | ("table" 'loct5') | import_dest1 | loct6 | sqlite_svr | ("table" 'loct6') | import_dest1 | loct7 | sqlite_svr | ("table" 'loct7') | import_dest1 | loct_empty | sqlite_svr | ("table" 'loct_empty') | import_dest1 | t1_constraint | sqlite_svr | ("table" 't1_constraint') | import_dest1 | tru_fk_table | sqlite_svr | ("table" 'tru_fk_table') | import_dest1 | tru_pk_table | sqlite_svr | ("table" 'tru_pk_table') | import_dest1 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest1 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest1 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | (28 rows) --Testcase 478: \d import_dest1.* Foreign table "import_dest1.T 0" Column | Type | Collation | Nullable | Default | FDW options --------+-----------------------------+-----------+----------+---------+-------------- C 1 | bigint | | | | (key 'true') c2 | bigint | | not null | | c3 | text | | | | c4 | timestamp with time zone | | | | c5 | timestamp without time zone | | | | c6 | character varying(10) | | | | c7 | character(10) | | | | c8 | text | | | | Server: sqlite_svr FDW options: ("table" 'T 0') Foreign table "import_dest1.T 1" Column | Type | Collation | Nullable | Default | FDW options --------+-----------------------------+-----------+----------+---------+-------------- C 1 | bigint | | | | (key 'true') c2 | bigint | | not null | | c3 | text | | | | c4 | timestamp with time zone | | | | c5 | timestamp without time zone | | | | c6 | character varying(10) | | | | c7 | character(10) | | | | c8 | text | | | | Server: sqlite_svr FDW options: ("table" 'T 1') Foreign table "import_dest1.T 2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- c1 | bigint | | | | (key 'true') c2 | text | | | | Server: sqlite_svr FDW options: ("table" 'T 2') Foreign table "import_dest1.T 3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- c1 | bigint | | | | (key 'true') c2 | bigint | | not null | | c3 | text | | | | Server: sqlite_svr FDW options: ("table" 'T 3') Foreign table "import_dest1.T 4" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- c1 | bigint | | | | (key 'true') c2 | bigint | | not null | | c3 | text | | | | Server: sqlite_svr FDW options: ("table" 'T 4') Foreign table "import_dest1.base_tbl" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | bigint | | | | Server: sqlite_svr FDW options: ("table" 'base_tbl') Foreign table "import_dest1.batch_table" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- x | bigint | | | | Server: sqlite_svr FDW options: ("table" 'batch_table') Foreign table "import_dest1.foreign_tbl" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- a | bigint | | | | (key 'true') b | bigint | | | | Server: sqlite_svr FDW options: ("table" 'foreign_tbl') Foreign table "import_dest1.ft3" Column | Type | Collation | Nullable | Default | FDW options --------+------+-----------+----------+---------+-------------- f1 | text | | | | (key 'true') f2 | text | | | | (key 'true') f3 | text | | | | (key 'true') Server: sqlite_svr FDW options: ("table" 'ft3') Foreign table "import_dest1.grem1" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- a | bigint | | | | (key 'true') b | bigint | | | | Server: sqlite_svr FDW options: ("table" 'grem1') Foreign table "import_dest1.loc1" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- f1 | bigint | | | | f2 | text | | | | id | bigint | | | | (key 'true') Server: sqlite_svr FDW options: ("table" 'loc1') Foreign table "import_dest1.local_tbl" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- c1 | bigint | | | | (key 'true') c2 | bigint | | | | c3 | text | | | | Server: sqlite_svr FDW options: ("table" 'local_tbl') Foreign table "import_dest1.loct" Column | Type | Collation | Nullable | Default | FDW options --------+------+-----------+----------+---------+------------- aa | text | | | | bb | text | | | | Server: sqlite_svr FDW options: ("table" 'loct') Foreign table "import_dest1.loct1" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- f1 | bigint | | | | f2 | bigint | | | | f3 | bigint | | | | Server: sqlite_svr FDW options: ("table" 'loct1') Foreign table "import_dest1.loct2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- f1 | bigint | | | | f2 | bigint | | | | f3 | bigint | | | | Server: sqlite_svr FDW options: ("table" 'loct2') Foreign table "import_dest1.loct3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | text | | | | Server: sqlite_svr FDW options: ("table" 'loct3') Foreign table "import_dest1.loct4" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | text | | | | Server: sqlite_svr FDW options: ("table" 'loct4') Foreign table "import_dest1.loct4_2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- f1 | bigint | | | | f2 | bigint | | | | f3 | bigint | | | | Server: sqlite_svr FDW options: ("table" 'loct4_2') Foreign table "import_dest1.loct5" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | text | | | | Server: sqlite_svr FDW options: ("table" 'loct5') Foreign table "import_dest1.loct6" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | text | | | | Server: sqlite_svr FDW options: ("table" 'loct6') Foreign table "import_dest1.loct7" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | text | | | | Server: sqlite_svr FDW options: ("table" 'loct7') Foreign table "import_dest1.loct_empty" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- c1 | bigint | | not null | | (key 'true') c2 | text | | | | Server: sqlite_svr FDW options: ("table" 'loct_empty') Foreign table "import_dest1.t1_constraint" Column | Type | Collation | Nullable | Default | FDW options --------+-----------------------------+-----------+----------+---------+-------------- c1 | bigint | | | | (key 'true') c2 | bigint | | not null | | c3 | text | | | | c4 | timestamp with time zone | | | | c5 | timestamp without time zone | | | | c6 | character varying(10) | | | | c7 | character(10) | | | | c8 | text | | | | Server: sqlite_svr FDW options: ("table" 't1_constraint') Foreign table "import_dest1.tru_fk_table" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- fkey | bigint | | | | Server: sqlite_svr FDW options: ("table" 'tru_fk_table') Foreign table "import_dest1.tru_pk_table" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- id | bigint | | | | (key 'true') Server: sqlite_svr FDW options: ("table" 'tru_pk_table') Foreign table "import_dest1.tru_rtable0" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- id | bigint | | | | (key 'true') Server: sqlite_svr FDW options: ("table" 'tru_rtable0') Foreign table "import_dest1.tru_rtable_child" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- id | bigint | | | | Server: sqlite_svr FDW options: ("table" 'tru_rtable_child') Foreign table "import_dest1.tru_rtable_parent" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- id | bigint | | | | Server: sqlite_svr FDW options: ("table" 'tru_rtable_parent') -- Options --Testcase 729: CREATE SCHEMA import_dest2; IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest2 OPTIONS (import_default 'true'); --Testcase 479: \det+ import_dest2.* List of foreign tables Schema | Table | Server | FDW options | Description --------------+-------------------+------------+-------------------------------+------------- import_dest2 | T 0 | sqlite_svr | ("table" 'T 0') | import_dest2 | T 1 | sqlite_svr | ("table" 'T 1') | import_dest2 | T 2 | sqlite_svr | ("table" 'T 2') | import_dest2 | T 3 | sqlite_svr | ("table" 'T 3') | import_dest2 | T 4 | sqlite_svr | ("table" 'T 4') | import_dest2 | base_tbl | sqlite_svr | ("table" 'base_tbl') | import_dest2 | batch_table | sqlite_svr | ("table" 'batch_table') | import_dest2 | foreign_tbl | sqlite_svr | ("table" 'foreign_tbl') | import_dest2 | ft3 | sqlite_svr | ("table" 'ft3') | import_dest2 | grem1 | sqlite_svr | ("table" 'grem1') | import_dest2 | loc1 | sqlite_svr | ("table" 'loc1') | import_dest2 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest2 | loct | sqlite_svr | ("table" 'loct') | import_dest2 | loct1 | sqlite_svr | ("table" 'loct1') | import_dest2 | loct2 | sqlite_svr | ("table" 'loct2') | import_dest2 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest2 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest2 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | import_dest2 | loct5 | sqlite_svr | ("table" 'loct5') | import_dest2 | loct6 | sqlite_svr | ("table" 'loct6') | import_dest2 | loct7 | sqlite_svr | ("table" 'loct7') | import_dest2 | loct_empty | sqlite_svr | ("table" 'loct_empty') | import_dest2 | t1_constraint | sqlite_svr | ("table" 't1_constraint') | import_dest2 | tru_fk_table | sqlite_svr | ("table" 'tru_fk_table') | import_dest2 | tru_pk_table | sqlite_svr | ("table" 'tru_pk_table') | import_dest2 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest2 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest2 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | (28 rows) --Testcase 480: \d import_dest2.* Foreign table "import_dest2.T 0" Column | Type | Collation | Nullable | Default | FDW options --------+-----------------------------+-----------+----------+---------+-------------- C 1 | bigint | | | | (key 'true') c2 | bigint | | not null | | c3 | text | | | | c4 | timestamp with time zone | | | | c5 | timestamp without time zone | | | | c6 | character varying(10) | | | | c7 | character(10) | | | | c8 | text | | | | Server: sqlite_svr FDW options: ("table" 'T 0') Foreign table "import_dest2.T 1" Column | Type | Collation | Nullable | Default | FDW options --------+-----------------------------+-----------+----------+---------+-------------- C 1 | bigint | | | | (key 'true') c2 | bigint | | not null | | c3 | text | | | | c4 | timestamp with time zone | | | | c5 | timestamp without time zone | | | | c6 | character varying(10) | | | | c7 | character(10) | | | | c8 | text | | | | Server: sqlite_svr FDW options: ("table" 'T 1') Foreign table "import_dest2.T 2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- c1 | bigint | | | | (key 'true') c2 | text | | | | Server: sqlite_svr FDW options: ("table" 'T 2') Foreign table "import_dest2.T 3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- c1 | bigint | | | | (key 'true') c2 | bigint | | not null | | c3 | text | | | | Server: sqlite_svr FDW options: ("table" 'T 3') Foreign table "import_dest2.T 4" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- c1 | bigint | | | | (key 'true') c2 | bigint | | not null | | c3 | text | | | | Server: sqlite_svr FDW options: ("table" 'T 4') Foreign table "import_dest2.base_tbl" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | bigint | | | | Server: sqlite_svr FDW options: ("table" 'base_tbl') Foreign table "import_dest2.batch_table" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- x | bigint | | | | Server: sqlite_svr FDW options: ("table" 'batch_table') Foreign table "import_dest2.foreign_tbl" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- a | bigint | | | | (key 'true') b | bigint | | | | Server: sqlite_svr FDW options: ("table" 'foreign_tbl') Foreign table "import_dest2.ft3" Column | Type | Collation | Nullable | Default | FDW options --------+------+-----------+----------+---------+-------------- f1 | text | | | | (key 'true') f2 | text | | | | (key 'true') f3 | text | | | | (key 'true') Server: sqlite_svr FDW options: ("table" 'ft3') Foreign table "import_dest2.grem1" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- a | bigint | | | | (key 'true') b | bigint | | | | Server: sqlite_svr FDW options: ("table" 'grem1') Foreign table "import_dest2.loc1" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- f1 | bigint | | | | f2 | text | | | | id | bigint | | | | (key 'true') Server: sqlite_svr FDW options: ("table" 'loc1') Foreign table "import_dest2.local_tbl" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- c1 | bigint | | | | (key 'true') c2 | bigint | | | | c3 | text | | | | Server: sqlite_svr FDW options: ("table" 'local_tbl') Foreign table "import_dest2.loct" Column | Type | Collation | Nullable | Default | FDW options --------+------+-----------+----------+---------+------------- aa | text | | | | bb | text | | | | Server: sqlite_svr FDW options: ("table" 'loct') Foreign table "import_dest2.loct1" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- f1 | bigint | | | | f2 | bigint | | | | f3 | bigint | | | | Server: sqlite_svr FDW options: ("table" 'loct1') Foreign table "import_dest2.loct2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- f1 | bigint | | | | f2 | bigint | | | | f3 | bigint | | | | Server: sqlite_svr FDW options: ("table" 'loct2') Foreign table "import_dest2.loct3" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | text | | | | Server: sqlite_svr FDW options: ("table" 'loct3') Foreign table "import_dest2.loct4" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | text | | | | Server: sqlite_svr FDW options: ("table" 'loct4') Foreign table "import_dest2.loct4_2" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- f1 | bigint | | | | f2 | bigint | | | | f3 | bigint | | | | Server: sqlite_svr FDW options: ("table" 'loct4_2') Foreign table "import_dest2.loct5" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | text | | | | Server: sqlite_svr FDW options: ("table" 'loct5') Foreign table "import_dest2.loct6" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | text | | | | Server: sqlite_svr FDW options: ("table" 'loct6') Foreign table "import_dest2.loct7" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- a | bigint | | | | b | text | | | | Server: sqlite_svr FDW options: ("table" 'loct7') Foreign table "import_dest2.loct_empty" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- c1 | bigint | | not null | | (key 'true') c2 | text | | | | Server: sqlite_svr FDW options: ("table" 'loct_empty') Foreign table "import_dest2.t1_constraint" Column | Type | Collation | Nullable | Default | FDW options --------+-----------------------------+-----------+----------+---------+-------------- c1 | bigint | | | | (key 'true') c2 | bigint | | not null | | c3 | text | | | | c4 | timestamp with time zone | | | | c5 | timestamp without time zone | | | | c6 | character varying(10) | | | | c7 | character(10) | | | | c8 | text | | | | Server: sqlite_svr FDW options: ("table" 't1_constraint') Foreign table "import_dest2.tru_fk_table" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- fkey | bigint | | | | Server: sqlite_svr FDW options: ("table" 'tru_fk_table') Foreign table "import_dest2.tru_pk_table" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- id | bigint | | | | (key 'true') Server: sqlite_svr FDW options: ("table" 'tru_pk_table') Foreign table "import_dest2.tru_rtable0" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+-------------- id | bigint | | | | (key 'true') Server: sqlite_svr FDW options: ("table" 'tru_rtable0') Foreign table "import_dest2.tru_rtable_child" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- id | bigint | | | | Server: sqlite_svr FDW options: ("table" 'tru_rtable_child') Foreign table "import_dest2.tru_rtable_parent" Column | Type | Collation | Nullable | Default | FDW options --------+--------+-----------+----------+---------+------------- id | bigint | | | | Server: sqlite_svr FDW options: ("table" 'tru_rtable_parent') -- Check LIMIT TO and EXCEPT --Testcase 730: CREATE SCHEMA import_dest3; IMPORT FOREIGN SCHEMA public LIMIT TO ("T 1", loct6, nonesuch) FROM SERVER sqlite_svr INTO import_dest3; --Testcase 481: \det+ import_dest3.* List of foreign tables Schema | Table | Server | FDW options | Description --------------+-------+------------+-------------------+------------- import_dest3 | T 1 | sqlite_svr | ("table" 'T 1') | import_dest3 | loct6 | sqlite_svr | ("table" 'loct6') | (2 rows) IMPORT FOREIGN SCHEMA public EXCEPT ("T 1", loct6, nonesuch) FROM SERVER sqlite_svr INTO import_dest3; --Testcase 482: \det+ import_dest3.* List of foreign tables Schema | Table | Server | FDW options | Description --------------+-------------------+------------+-------------------------------+------------- import_dest3 | T 0 | sqlite_svr | ("table" 'T 0') | import_dest3 | T 1 | sqlite_svr | ("table" 'T 1') | import_dest3 | T 2 | sqlite_svr | ("table" 'T 2') | import_dest3 | T 3 | sqlite_svr | ("table" 'T 3') | import_dest3 | T 4 | sqlite_svr | ("table" 'T 4') | import_dest3 | base_tbl | sqlite_svr | ("table" 'base_tbl') | import_dest3 | batch_table | sqlite_svr | ("table" 'batch_table') | import_dest3 | foreign_tbl | sqlite_svr | ("table" 'foreign_tbl') | import_dest3 | ft3 | sqlite_svr | ("table" 'ft3') | import_dest3 | grem1 | sqlite_svr | ("table" 'grem1') | import_dest3 | loc1 | sqlite_svr | ("table" 'loc1') | import_dest3 | local_tbl | sqlite_svr | ("table" 'local_tbl') | import_dest3 | loct | sqlite_svr | ("table" 'loct') | import_dest3 | loct1 | sqlite_svr | ("table" 'loct1') | import_dest3 | loct2 | sqlite_svr | ("table" 'loct2') | import_dest3 | loct3 | sqlite_svr | ("table" 'loct3') | import_dest3 | loct4 | sqlite_svr | ("table" 'loct4') | import_dest3 | loct4_2 | sqlite_svr | ("table" 'loct4_2') | import_dest3 | loct5 | sqlite_svr | ("table" 'loct5') | import_dest3 | loct6 | sqlite_svr | ("table" 'loct6') | import_dest3 | loct7 | sqlite_svr | ("table" 'loct7') | import_dest3 | loct_empty | sqlite_svr | ("table" 'loct_empty') | import_dest3 | t1_constraint | sqlite_svr | ("table" 't1_constraint') | import_dest3 | tru_fk_table | sqlite_svr | ("table" 'tru_fk_table') | import_dest3 | tru_pk_table | sqlite_svr | ("table" 'tru_pk_table') | import_dest3 | tru_rtable0 | sqlite_svr | ("table" 'tru_rtable0') | import_dest3 | tru_rtable_child | sqlite_svr | ("table" 'tru_rtable_child') | import_dest3 | tru_rtable_parent | sqlite_svr | ("table" 'tru_rtable_parent') | (28 rows) -- Assorted error cases IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO import_dest3; ERROR: relation "T 0" already exists CONTEXT: importing foreign table "T 0" IMPORT FOREIGN SCHEMA public FROM SERVER sqlite_svr INTO notthere; ERROR: schema "notthere" does not exist IMPORT FOREIGN SCHEMA public FROM SERVER nowhere INTO notthere; ERROR: server "nowhere" does not exist /* -- Skip these test, sqlite fdw does not support fetch_size option, partition table -- Check case of a type present only on the remote server. -- We can fake this by dropping the type locally in our transaction. CREATE TYPE "Colors" AS ENUM ('red', 'green', 'blue'); CREATE TABLE import_source.t5 (c1 int, c2 text collate "C", "Col" "Colors"); CREATE SCHEMA import_dest5; BEGIN; DROP TYPE "Colors" CASCADE; IMPORT FOREIGN SCHEMA import_source LIMIT TO (t5) FROM SERVER loopback INTO import_dest5; -- ERROR ROLLBACK; BEGIN; CREATE SERVER fetch101 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( fetch_size '101' ); SELECT count(*) FROM pg_foreign_server WHERE srvname = 'fetch101' AND srvoptions @> array['fetch_size=101']; ALTER SERVER fetch101 OPTIONS( SET fetch_size '202' ); SELECT count(*) FROM pg_foreign_server WHERE srvname = 'fetch101' AND srvoptions @> array['fetch_size=101']; SELECT count(*) FROM pg_foreign_server WHERE srvname = 'fetch101' AND srvoptions @> array['fetch_size=202']; CREATE FOREIGN TABLE table30000 ( x int ) SERVER fetch101 OPTIONS ( fetch_size '30000' ); SELECT COUNT(*) FROM pg_foreign_table WHERE ftrelid = 'table30000'::regclass AND ftoptions @> array['fetch_size=30000']; ALTER FOREIGN TABLE table30000 OPTIONS ( SET fetch_size '60000'); SELECT COUNT(*) FROM pg_foreign_table WHERE ftrelid = 'table30000'::regclass AND ftoptions @> array['fetch_size=30000']; SELECT COUNT(*) FROM pg_foreign_table WHERE ftrelid = 'table30000'::regclass AND ftoptions @> array['fetch_size=60000']; ROLLBACK; -- =================================================================== -- test partitionwise joins -- =================================================================== SET enable_partitionwise_join=on; CREATE TABLE fprt1 (a int, b int, c varchar) PARTITION BY RANGE(a); CREATE TABLE fprt1_p1 (LIKE fprt1); CREATE TABLE fprt1_p2 (LIKE fprt1); ALTER TABLE fprt1_p1 SET (autovacuum_enabled = 'false'); ALTER TABLE fprt1_p2 SET (autovacuum_enabled = 'false'); INSERT INTO fprt1_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 2) i; INSERT INTO fprt1_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 2) i; CREATE FOREIGN TABLE ftprt1_p1 PARTITION OF fprt1 FOR VALUES FROM (0) TO (250) SERVER loopback OPTIONS (table_name 'fprt1_p1', use_remote_estimate 'true'); CREATE FOREIGN TABLE ftprt1_p2 PARTITION OF fprt1 FOR VALUES FROM (250) TO (500) SERVER loopback OPTIONS (TABLE_NAME 'fprt1_p2'); ANALYZE fprt1; ANALYZE fprt1_p1; ANALYZE fprt1_p2; CREATE TABLE fprt2 (a int, b int, c varchar) PARTITION BY RANGE(b); CREATE TABLE fprt2_p1 (LIKE fprt2); CREATE TABLE fprt2_p2 (LIKE fprt2); ALTER TABLE fprt2_p1 SET (autovacuum_enabled = 'false'); ALTER TABLE fprt2_p2 SET (autovacuum_enabled = 'false'); INSERT INTO fprt2_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 3) i; INSERT INTO fprt2_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 3) i; CREATE FOREIGN TABLE ftprt2_p1 (b int, c varchar, a int) SERVER loopback OPTIONS (table_name 'fprt2_p1', use_remote_estimate 'true'); ALTER TABLE fprt2 ATTACH PARTITION ftprt2_p1 FOR VALUES FROM (0) TO (250); CREATE FOREIGN TABLE ftprt2_p2 PARTITION OF fprt2 FOR VALUES FROM (250) TO (500) SERVER loopback OPTIONS (table_name 'fprt2_p2', use_remote_estimate 'true'); ANALYZE fprt2; ANALYZE fprt2_p1; ANALYZE fprt2_p2; -- inner join three tables EXPLAIN (COSTS OFF) SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3; -- left outer join + nullable clause EXPLAIN (VERBOSE, COSTS OFF) SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3; -- with whole-row reference; partitionwise join does not apply EXPLAIN (COSTS OFF) SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; SELECT t1.wr, t2.wr FROM (SELECT t1 wr, a FROM fprt1 t1 WHERE t1.a % 25 = 0) t1 FULL JOIN (SELECT t2 wr, b FROM fprt2 t2 WHERE t2.b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY 1,2; -- join with lateral reference EXPLAIN (COSTS OFF) SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2; -- with PHVs, partitionwise join selected but no join pushdown EXPLAIN (COSTS OFF) SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; SELECT t1.a, t1.phv, t2.b, t2.phv FROM (SELECT 't1_phv' phv, * FROM fprt1 WHERE a % 25 = 0) t1 FULL JOIN (SELECT 't2_phv' phv, * FROM fprt2 WHERE b % 25 = 0) t2 ON (t1.a = t2.b) ORDER BY t1.a, t2.b; -- test FOR UPDATE; partitionwise join does not apply EXPLAIN (COSTS OFF) SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; SELECT t1.a, t2.b FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) WHERE t1.a % 25 = 0 ORDER BY 1,2 FOR UPDATE OF t1; RESET enable_partitionwise_join; -- =================================================================== -- test partitionwise aggregates -- =================================================================== CREATE TABLE pagg_tab (a int, b int, c text) PARTITION BY RANGE(a); CREATE TABLE pagg_tab_p1 (LIKE pagg_tab); CREATE TABLE pagg_tab_p2 (LIKE pagg_tab); CREATE TABLE pagg_tab_p3 (LIKE pagg_tab); INSERT INTO pagg_tab_p1 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 10; INSERT INTO pagg_tab_p2 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 20 and (i % 30) >= 10; INSERT INTO pagg_tab_p3 SELECT i % 30, i % 50, to_char(i/30, 'FM0000') FROM generate_series(1, 3000) i WHERE (i % 30) < 30 and (i % 30) >= 20; -- Create foreign partitions CREATE FOREIGN TABLE fpagg_tab_p1 PARTITION OF pagg_tab FOR VALUES FROM (0) TO (10) SERVER loopback OPTIONS (table_name 'pagg_tab_p1'); CREATE FOREIGN TABLE fpagg_tab_p2 PARTITION OF pagg_tab FOR VALUES FROM (10) TO (20) SERVER loopback OPTIONS (table_name 'pagg_tab_p2'); CREATE FOREIGN TABLE fpagg_tab_p3 PARTITION OF pagg_tab FOR VALUES FROM (20) TO (30) SERVER loopback OPTIONS (table_name 'pagg_tab_p3'); ANALYZE pagg_tab; ANALYZE fpagg_tab_p1; ANALYZE fpagg_tab_p2; ANALYZE fpagg_tab_p3; -- When GROUP BY clause matches with PARTITION KEY. -- Plan with partitionwise aggregates is disabled SET enable_partitionwise_aggregate TO false; EXPLAIN (COSTS OFF) SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; -- Plan with partitionwise aggregates is enabled SET enable_partitionwise_aggregate TO true; EXPLAIN (COSTS OFF) SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1; -- Check with whole-row reference -- Should have all the columns in the target list for the given relation EXPLAIN (VERBOSE, COSTS OFF) SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1; -- When GROUP BY clause does not match with PARTITION KEY. EXPLAIN (COSTS OFF) SELECT b, avg(a), max(a), count(*) FROM pagg_tab GROUP BY b HAVING sum(a) < 700 ORDER BY 1; */ /* -- Skip these tests, sqlite fdw does not support nosuper user. -- =================================================================== -- access rights and superuser -- =================================================================== -- Non-superuser cannot create a FDW without a password in the connstr CREATE ROLE regress_nosuper NOSUPERUSER; GRANT USAGE ON FOREIGN DATA WRAPPER sqlite_fdw TO regress_nosuper; SET ROLE regress_nosuper; SHOW is_superuser; -- This will be OK, we can create the FDW DO $d$ BEGIN EXECUTE $$CREATE SERVER sqlite_nopw FOREIGN DATA WRAPPER sqlite_fdw OPTIONS (database '/tmp/sqlitefdw_test_post.db')$$; END; $d$; -- But creation of user mappings for non-superusers should fail CREATE USER MAPPING FOR public SERVER sqlite_nopw; CREATE USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw; CREATE FOREIGN TABLE ft1_nopw ( c1 int OPTIONS (key 'true'), c2 int NOT NULL, c3 text, c4 timestamptz, c5 timestamp, c6 varchar(10), c7 char(10) default 'ft1', c8 text ) SERVER sqlite_nopw; ALTER FOREIGN TABLE ft1_nopw OPTIONS (table 'T 1'); ALTER FOREIGN TABLE ft1_nopw ALTER COLUMN c1 OPTIONS (column_name 'C 1'); SELECT * FROM ft1_nopw LIMIT 1; -- If we add a password to the connstr it'll fail, because we don't allow passwords -- in connstrs only in user mappings. DO $d$ BEGIN EXECUTE $$ALTER SERVER sqlite_nopw OPTIONS (ADD password 'dummypw')$$; END; $d$; -- If we add a password for our user mapping instead, we should get a different -- error because the password wasn't actually *used* when we run with trust auth. -- -- This won't work with installcheck, but neither will most of the FDW checks. ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD password 'dummypw'); SELECT * FROM ft1_nopw LIMIT 1; -- Unpriv user cannot make the mapping passwordless ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD password_required 'false'); SELECT * FROM ft1_nopw LIMIT 1; RESET ROLE; -- But the superuser can ALTER USER MAPPING FOR regress_nosuper SERVER sqlite_nopw OPTIONS (ADD password_required 'false'); SET ROLE regress_nosuper; -- Should finally work now SELECT * FROM ft1_nopw LIMIT 1; -- unpriv user also cannot set sslcert / sslkey on the user mapping -- first set password_required so we see the right error messages ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (SET password_required 'true'); ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD sslcert 'foo.crt'); ALTER USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw OPTIONS (ADD sslkey 'foo.key'); -- We're done with the role named after a specific user and need to check the -- changes to the public mapping. DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_nopw; -- This will fail again as it'll resolve the user mapping for public, which -- lacks password_required=false SELECT * FROM ft1_nopw LIMIT 1; RESET ROLE; -- The user mapping for public is passwordless and lacks the password_required=false -- mapping option, but will work because the current user is a superuser. SELECT * FROM ft1_nopw LIMIT 1; -- cleanup DROP USER MAPPING FOR public SERVER sqlite_nopw; DROP OWNED BY regress_nosuper; DROP ROLE regress_nosuper; -- Clean-up RESET enable_partitionwise_aggregate; */ -- Two-phase transactions are not supported. BEGIN; --Testcase 731: SELECT count(*) FROM ft1; count ------- 822 (1 row) -- error here --Testcase 732: PREPARE TRANSACTION 'fdw_tpc'; ERROR: cannot prepare a transaction that modified remote tables ROLLBACK; WARNING: there is no transaction in progress -- =================================================================== -- reestablish new connection -- =================================================================== -- -- Test case relative with option application_name is not suitable for SQLite FDW. -- -- Because this option is in libpq of postgres. -- -- Change application_name of remote connection to special one -- -- so that we can easily terminate the connection later. -- ALTER SERVER sqlite_svr OPTIONS (application_name 'fdw_retry_check'); -- -- If debug_invalidate_system_caches_always is active, it results in -- -- dropping remote connections after every transaction, making it -- -- impossible to test termination meaningfully. So turn that off -- -- for this test. -- SET debug_invalidate_system_caches_always = 0; -- -- Make sure we have a remote connection. -- SELECT 1 FROM ft1 LIMIT 1; -- -- Terminate the remote connection and wait for the termination to complete. -- SELECT pg_terminate_backend(pid, 180000) FROM pg_stat_activity -- WHERE application_name = 'fdw_retry_check'; -- -- This query should detect the broken connection when starting new remote -- -- transaction, reestablish new connection, and then succeed. -- BEGIN; -- SELECT 1 FROM ft1 LIMIT 1; -- -- If we detect the broken connection when starting a new remote -- -- subtransaction, we should fail instead of establishing a new connection. -- -- Terminate the remote connection and wait for the termination to complete. -- SELECT pg_terminate_backend(pid, 180000) FROM pg_stat_activity -- WHERE application_name = 'fdw_retry_check'; -- SAVEPOINT s; -- -- The text of the error might vary across platforms, so only show SQLSTATE. -- \set VERBOSITY sqlstate -- SELECT 1 FROM ft1 LIMIT 1; -- should fail -- \set VERBOSITY default -- COMMIT; -- RESET debug_invalidate_system_caches_always; -- ============================================================================= -- test connection invalidation cases and sqlite_fdw_get_connections function -- ============================================================================= -- Let's ensure to close all the existing cached connections. SELECT 1 FROM sqlite_fdw_disconnect_all(); ?column? ---------- 1 (1 row) -- No cached connections, so no records should be output. SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name ------------- (0 rows) -- This test case is for closing the connection in sqlitefdw_xact_callback BEGIN; -- Connection xact depth becomes 1 i.e. the connection is in midst of the xact. SELECT 1 FROM ft1 LIMIT 1; ?column? ---------- 1 (1 row) SELECT 1 FROM ft7 LIMIT 1; ?column? ---------- 1 (1 row) -- List all the existing cached connections. sqlite_svr and sqlite_svr3 should be -- output. SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name ------------- sqlite_svr sqlite_svr3 (2 rows) -- Connections are not closed at the end of the alter and drop statements. -- That's because the connections are in midst of this xact, -- they are just marked as invalid in sqlitefdw_inval_callback. ALTER SERVER sqlite_svr OPTIONS (ADD keep_connections 'off'); DROP SERVER sqlite_svr3 CASCADE; NOTICE: drop cascades to 2 other objects DETAIL: drop cascades to user mapping for public on server sqlite_svr3 drop cascades to foreign table ft7 -- List all the existing cached connections. sqlite_svr and sqlite_svr3 -- should be output as invalid connections. Also the server name for -- sqlite_svr3 should be NULL because the server was dropped. SELECT * FROM sqlite_fdw_get_connections() ORDER BY 1; server_name | valid -------------+------- sqlite_svr | f | f (2 rows) -- The invalid connections get closed in sqlitefdw_xact_callback during commit. COMMIT; ALTER SERVER sqlite_svr OPTIONS (DROP keep_connections); -- All cached connections were closed while committing above xact, so no -- records should be output. SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name ------------- (0 rows) -- ======================================================================= -- test sqlite_fdw_disconnect and sqlite_fdw_disconnect_all functions -- ======================================================================= BEGIN; -- Ensure to cache loopback connection. SELECT 1 FROM ft1 LIMIT 1; ?column? ---------- 1 (1 row) -- Ensure to cache loopback2 connection. SELECT 1 FROM ft6 LIMIT 1; ?column? ---------- 1 (1 row) -- List all the existing cached connections. sqlite_svr and sqlite_svr2 should be -- output. SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name ------------- sqlite_svr sqlite_svr2 (2 rows) -- Issue a warning and return false as sqlite_svr connection is still in use and -- can not be closed. SELECT sqlite_fdw_disconnect('sqlite_svr'); WARNING: cannot close connection for server "sqlite_svr" because it is still in use sqlite_fdw_disconnect ----------------------- f (1 row) -- List all the existing cached connections. sqlite_svr and sqlite_svr2 should be -- output. SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name ------------- sqlite_svr sqlite_svr2 (2 rows) -- Return false as connections are still in use, warnings are issued. -- But disable warnings temporarily because the order of them is not stable. SET client_min_messages = 'ERROR'; SELECT sqlite_fdw_disconnect_all(); sqlite_fdw_disconnect_all --------------------------- f (1 row) RESET client_min_messages; COMMIT; -- Ensure that sqlite_svr2 connection is closed. SELECT 1 FROM sqlite_fdw_disconnect('sqlite_svr2'); ?column? ---------- 1 (1 row) SELECT server_name FROM sqlite_fdw_get_connections() WHERE server_name = 'sqlite_svr2'; server_name ------------- (0 rows) -- Return false as sqlite_svr2 connection is closed already. SELECT sqlite_fdw_disconnect('sqlite_svr2'); sqlite_fdw_disconnect ----------------------- f (1 row) -- Return an error as there is no foreign server with given name. SELECT sqlite_fdw_disconnect('unknownserver'); ERROR: server "unknownserver" does not exist -- Let's ensure to close all the existing cached connections. SELECT 1 FROM sqlite_fdw_disconnect_all(); ?column? ---------- 1 (1 row) -- No cached connections, so no records should be output. SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name ------------- (0 rows) -- ============================================================================= -- test case for having multiple cached connections for a foreign server -- ============================================================================= CREATE ROLE regress_multi_conn_user1 SUPERUSER; CREATE ROLE regress_multi_conn_user2 SUPERUSER; CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; BEGIN; -- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user1 SET ROLE regress_multi_conn_user1; SELECT 1 FROM ft1 LIMIT 1; ?column? ---------- 1 (1 row) RESET ROLE; -- Will cache sqlite_svr connection with user mapping for regress_multi_conn_user2 SET ROLE regress_multi_conn_user2; SELECT 1 FROM ft1 LIMIT 1; ?column? ---------- 1 (1 row) RESET ROLE; -- Should output two connections for sqlite_svr server SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name ------------- sqlite_svr (1 row) COMMIT; -- Let's ensure to close all the existing cached connections. SELECT 1 FROM sqlite_fdw_disconnect_all(); ?column? ---------- 1 (1 row) -- No cached connections, so no records should be output. SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name ------------- (0 rows) -- Clean up DROP USER MAPPING FOR regress_multi_conn_user1 SERVER sqlite_svr; DROP USER MAPPING FOR regress_multi_conn_user2 SERVER sqlite_svr; DROP ROLE regress_multi_conn_user1; DROP ROLE regress_multi_conn_user2; -- =================================================================== -- Test foreign server level option keep_connections -- =================================================================== -- By default, the connections associated with foreign server are cached i.e. -- keep_connections option is on. Set it to off. ALTER SERVER sqlite_svr OPTIONS (keep_connections 'off'); -- connection to sqlite_svr server is closed at the end of xact -- as keep_connections was set to off. SELECT 1 FROM ft1 LIMIT 1; ?column? ---------- 1 (1 row) -- No cached connections, so no records should be output. SELECT server_name FROM sqlite_fdw_get_connections() ORDER BY 1; server_name ------------- (0 rows) ALTER SERVER sqlite_svr OPTIONS (SET keep_connections 'on'); -- =================================================================== -- batch insert -- =================================================================== BEGIN; CREATE SERVER batch10 FOREIGN DATA WRAPPER sqlite_fdw OPTIONS( batch_size '10' ); SELECT count(*) FROM pg_foreign_server WHERE srvname = 'batch10' AND srvoptions @> array['batch_size=10']; count ------- 1 (1 row) ALTER SERVER batch10 OPTIONS( SET batch_size '20' ); SELECT count(*) FROM pg_foreign_server WHERE srvname = 'batch10' AND srvoptions @> array['batch_size=10']; count ------- 0 (1 row) SELECT count(*) FROM pg_foreign_server WHERE srvname = 'batch10' AND srvoptions @> array['batch_size=20']; count ------- 1 (1 row) CREATE FOREIGN TABLE table30 ( x int ) SERVER batch10 OPTIONS ( batch_size '30' ); SELECT COUNT(*) FROM pg_foreign_table WHERE ftrelid = 'table30'::regclass AND ftoptions @> array['batch_size=30']; count ------- 1 (1 row) ALTER FOREIGN TABLE table30 OPTIONS ( SET batch_size '40'); SELECT COUNT(*) FROM pg_foreign_table WHERE ftrelid = 'table30'::regclass AND ftoptions @> array['batch_size=30']; count ------- 0 (1 row) SELECT COUNT(*) FROM pg_foreign_table WHERE ftrelid = 'table30'::regclass AND ftoptions @> array['batch_size=40']; count ------- 1 (1 row) ROLLBACK; CREATE FOREIGN TABLE ftable ( x int OPTIONS (key 'true') ) SERVER sqlite_svr OPTIONS ( table 'batch_table', batch_size '10' ); EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable SELECT * FROM generate_series(1, 10) i; QUERY PLAN ----------------------------------------------------- Insert on public.ftable Batch Size: 10 -> Function Scan on pg_catalog.generate_series i Output: i.i Function Call: generate_series(1, 10) (5 rows) INSERT INTO ftable SELECT * FROM generate_series(1, 10) i; INSERT INTO ftable SELECT * FROM generate_series(11, 31) i; INSERT INTO ftable VALUES (32); INSERT INTO ftable VALUES (33), (34); SELECT COUNT(*) FROM ftable; count ------- 34 (1 row) DELETE FROM ftable; DROP FOREIGN TABLE ftable; -- try if large batches exceed max number of bind parameters CREATE FOREIGN TABLE ftable ( x int OPTIONS (key 'true') ) SERVER sqlite_svr OPTIONS ( table 'batch_table', batch_size '100000' ); INSERT INTO ftable SELECT * FROM generate_series(1, 70000) i; SELECT COUNT(*) FROM ftable; count ------- 70000 (1 row) DELETE FROM ftable; DROP FOREIGN TABLE ftable; -- Disable batch insert CREATE FOREIGN TABLE ftable ( x int ) SERVER sqlite_svr OPTIONS ( table 'batch_table', batch_size '1' ); EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable VALUES (1), (2); QUERY PLAN ------------------------------------ Insert on public.ftable Batch Size: 1 -> Values Scan on "*VALUES*" Output: "*VALUES*".column1 (4 rows) INSERT INTO ftable VALUES (1), (2); SELECT COUNT(*) FROM ftable; count ------- 2 (1 row) DROP FOREIGN TABLE ftable; -- DROP TABLE batch_table; -- -- Use partitioning -- CREATE TABLE batch_table ( x int ) PARTITION BY HASH (x); -- CREATE TABLE batch_table_p0 (LIKE batch_table); -- CREATE FOREIGN TABLE batch_table_p0f -- PARTITION OF batch_table -- FOR VALUES WITH (MODULUS 3, REMAINDER 0) -- SERVER sqlite_svr -- OPTIONS (table 'batch_table_p0', batch_size '10'); -- CREATE TABLE batch_table_p1 (LIKE batch_table); -- CREATE FOREIGN TABLE batch_table_p1f -- PARTITION OF batch_table -- FOR VALUES WITH (MODULUS 3, REMAINDER 1) -- SERVER sqlite_svr -- OPTIONS (table 'batch_table_p1', batch_size '1'); -- CREATE TABLE batch_table_p2 -- PARTITION OF batch_table -- FOR VALUES WITH (MODULUS 3, REMAINDER 2); -- INSERT INTO "S 1".batch_table SELECT * FROM generate_series(1, 66) i; -- SELECT COUNT(*) FROM "S 1".batch_table; -- -- Check that enabling batched inserts doesn't interfere with cross-partition -- -- updates -- CREATE TABLE batch_cp_upd_test (a int) PARTITION BY LIST (a); -- CREATE TABLE batch_cp_upd_test1 (LIKE batch_cp_upd_test); -- CREATE FOREIGN TABLE batch_cp_upd_test1_f -- PARTITION OF batch_cp_upd_test -- FOR VALUES IN (1) -- SERVER sqlite_svr -- OPTIONS (table_name 'batch_cp_upd_test1', batch_size '10'); -- CREATE TABLE batch_cp_up_test1 PARTITION OF batch_cp_upd_test -- FOR VALUES IN (2); -- INSERT INTO batch_cp_upd_test VALUES (1), (2); -- -- The following moves a row from the local partition to the foreign one -- UPDATE batch_cp_upd_test t SET a = 1 FROM (VALUES (1), (2)) s(a) WHERE t.a = s.a; -- SELECT tableoid::regclass, * FROM batch_cp_upd_test; -- -- Clean up -- DROP TABLE batch_table, batch_cp_upd_test, batch_table_p0, batch_table_p1 CASCADE; -- -- Use partitioning -- ALTER SERVER loopback OPTIONS (ADD batch_size '10'); -- CREATE TABLE batch_table ( x int, field1 text, field2 text) PARTITION BY HASH (x); -- CREATE TABLE batch_table_p0 (LIKE batch_table); -- ALTER TABLE batch_table_p0 ADD CONSTRAINT p0_pkey PRIMARY KEY (x); -- CREATE FOREIGN TABLE batch_table_p0f -- PARTITION OF batch_table -- FOR VALUES WITH (MODULUS 2, REMAINDER 0) -- SERVER loopback -- OPTIONS (table_name 'batch_table_p0'); -- CREATE TABLE batch_table_p1 (LIKE batch_table); -- ALTER TABLE batch_table_p1 ADD CONSTRAINT p1_pkey PRIMARY KEY (x); -- CREATE FOREIGN TABLE batch_table_p1f -- PARTITION OF batch_table -- FOR VALUES WITH (MODULUS 2, REMAINDER 1) -- SERVER loopback -- OPTIONS (table_name 'batch_table_p1'); -- INSERT INTO batch_table SELECT i, 'test'||i, 'test'|| i FROM generate_series(1, 50) i; -- SELECT COUNT(*) FROM batch_table; -- SELECT * FROM batch_table ORDER BY x; -- ALTER SERVER loopback OPTIONS (DROP batch_size); -- =================================================================== -- test asynchronous execution -- =================================================================== -- ALTER SERVER loopback OPTIONS (DROP extensions); -- ALTER SERVER loopback OPTIONS (ADD async_capable 'true'); -- ALTER SERVER loopback2 OPTIONS (ADD async_capable 'true'); -- CREATE TABLE async_pt (a int, b int, c text) PARTITION BY RANGE (a); -- CREATE TABLE base_tbl1 (a int, b int, c text); -- CREATE TABLE base_tbl2 (a int, b int, c text); -- CREATE FOREIGN TABLE async_p1 PARTITION OF async_pt FOR VALUES FROM (1000) TO (2000) -- SERVER loopback OPTIONS (table_name 'base_tbl1'); -- CREATE FOREIGN TABLE async_p2 PARTITION OF async_pt FOR VALUES FROM (2000) TO (3000) -- SERVER loopback2 OPTIONS (table_name 'base_tbl2'); -- INSERT INTO async_p1 SELECT 1000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; -- INSERT INTO async_p2 SELECT 2000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; -- ANALYZE async_pt; -- -- simple queries -- CREATE TABLE result_tbl (a int, b int, c text); -- EXPLAIN (VERBOSE, COSTS OFF) -- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b % 100 = 0; -- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b % 100 = 0; -- SELECT * FROM result_tbl ORDER BY a; -- DELETE FROM result_tbl; -- EXPLAIN (VERBOSE, COSTS OFF) -- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; -- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; -- SELECT * FROM result_tbl ORDER BY a; -- DELETE FROM result_tbl; -- -- Check case where multiple partitions use the same connection -- CREATE TABLE base_tbl3 (a int, b int, c text); -- CREATE FOREIGN TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000) -- SERVER loopback2 OPTIONS (table_name 'base_tbl3'); -- INSERT INTO async_p3 SELECT 3000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; -- ANALYZE async_pt; -- EXPLAIN (VERBOSE, COSTS OFF) -- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; -- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; -- SELECT * FROM result_tbl ORDER BY a; -- DELETE FROM result_tbl; -- DROP FOREIGN TABLE async_p3; -- DROP TABLE base_tbl3; -- -- Check case where the partitioned table has local/remote partitions -- CREATE TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000); -- INSERT INTO async_p3 SELECT 3000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i; -- ANALYZE async_pt; -- EXPLAIN (VERBOSE, COSTS OFF) -- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; -- INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505; -- SELECT * FROM result_tbl ORDER BY a; -- DELETE FROM result_tbl; -- -- partitionwise joins -- SET enable_partitionwise_join TO true; -- CREATE TABLE join_tbl (a1 int, b1 int, c1 text, a2 int, b2 int, c2 text); -- EXPLAIN (VERBOSE, COSTS OFF) -- INSERT INTO join_tbl SELECT * FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; -- INSERT INTO join_tbl SELECT * FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; -- SELECT * FROM join_tbl ORDER BY a1; -- DELETE FROM join_tbl; -- RESET enable_partitionwise_join; -- -- Test rescan of an async Append node with do_exec_prune=false -- SET enable_hashjoin TO false; -- EXPLAIN (VERBOSE, COSTS OFF) -- INSERT INTO join_tbl SELECT * FROM async_p1 t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; -- INSERT INTO join_tbl SELECT * FROM async_p1 t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0; -- SELECT * FROM join_tbl ORDER BY a1; -- DELETE FROM join_tbl; -- RESET enable_hashjoin; -- -- Test interaction of async execution with plan-time partition pruning -- EXPLAIN (VERBOSE, COSTS OFF) -- SELECT * FROM async_pt WHERE a < 3000; -- EXPLAIN (VERBOSE, COSTS OFF) -- SELECT * FROM async_pt WHERE a < 2000; -- -- Test interaction of async execution with run-time partition pruning -- SET plan_cache_mode TO force_generic_plan; -- PREPARE async_pt_query (int, int) AS -- INSERT INTO result_tbl SELECT * FROM async_pt WHERE a < $1 AND b === $2; -- EXPLAIN (VERBOSE, COSTS OFF) -- EXECUTE async_pt_query (3000, 505); -- EXECUTE async_pt_query (3000, 505); -- SELECT * FROM result_tbl ORDER BY a; -- DELETE FROM result_tbl; -- EXPLAIN (VERBOSE, COSTS OFF) -- EXECUTE async_pt_query (2000, 505); -- EXECUTE async_pt_query (2000, 505); -- SELECT * FROM result_tbl ORDER BY a; -- DELETE FROM result_tbl; -- RESET plan_cache_mode; -- CREATE TABLE local_tbl(a int, b int, c text); -- INSERT INTO local_tbl VALUES (1505, 505, 'foo'), (2505, 505, 'bar'); -- ANALYZE local_tbl; -- CREATE INDEX base_tbl1_idx ON base_tbl1 (a); -- CREATE INDEX base_tbl2_idx ON base_tbl2 (a); -- CREATE INDEX async_p3_idx ON async_p3 (a); -- ANALYZE base_tbl1; -- ANALYZE base_tbl2; -- ANALYZE async_p3; -- ALTER FOREIGN TABLE async_p1 OPTIONS (use_remote_estimate 'true'); -- ALTER FOREIGN TABLE async_p2 OPTIONS (use_remote_estimate 'true'); -- EXPLAIN (VERBOSE, COSTS OFF) -- SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; -- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) -- SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; -- SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar'; -- ALTER FOREIGN TABLE async_p1 OPTIONS (DROP use_remote_estimate); -- ALTER FOREIGN TABLE async_p2 OPTIONS (DROP use_remote_estimate); -- DROP TABLE local_tbl; -- DROP INDEX base_tbl1_idx; -- DROP INDEX base_tbl2_idx; -- DROP INDEX async_p3_idx; -- -- Test that pending requests are processed properly -- SET enable_mergejoin TO false; -- SET enable_hashjoin TO false; -- EXPLAIN (VERBOSE, COSTS OFF) -- SELECT * FROM async_pt t1, async_p2 t2 WHERE t1.a = t2.a AND t1.b === 505; -- SELECT * FROM async_pt t1, async_p2 t2 WHERE t1.a = t2.a AND t1.b === 505; -- EXPLAIN (VERBOSE, COSTS OFF) -- SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; -- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) -- SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; -- SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1; -- -- Check with foreign modify -- CREATE TABLE local_tbl (a int, b int, c text); -- INSERT INTO local_tbl VALUES (1505, 505, 'foo'); -- CREATE TABLE base_tbl3 (a int, b int, c text); -- CREATE FOREIGN TABLE remote_tbl (a int, b int, c text) -- SERVER loopback OPTIONS (table_name 'base_tbl3'); -- INSERT INTO remote_tbl VALUES (2505, 505, 'bar'); -- CREATE TABLE base_tbl4 (a int, b int, c text); -- CREATE FOREIGN TABLE insert_tbl (a int, b int, c text) -- SERVER loopback OPTIONS (table_name 'base_tbl4'); -- EXPLAIN (VERBOSE, COSTS OFF) -- INSERT INTO insert_tbl (SELECT * FROM local_tbl UNION ALL SELECT * FROM remote_tbl); -- INSERT INTO insert_tbl (SELECT * FROM local_tbl UNION ALL SELECT * FROM remote_tbl); -- SELECT * FROM insert_tbl ORDER BY a; -- -- Check with direct modify -- EXPLAIN (VERBOSE, COSTS OFF) -- WITH t AS (UPDATE remote_tbl SET c = c || c RETURNING *) -- INSERT INTO join_tbl SELECT * FROM async_pt LEFT JOIN t ON (async_pt.a = t.a AND async_pt.b = t.b) WHERE async_pt.b === 505; -- WITH t AS (UPDATE remote_tbl SET c = c || c RETURNING *) -- INSERT INTO join_tbl SELECT * FROM async_pt LEFT JOIN t ON (async_pt.a = t.a AND async_pt.b = t.b) WHERE async_pt.b === 505; -- SELECT * FROM join_tbl ORDER BY a1; -- DELETE FROM join_tbl; -- DROP TABLE local_tbl; -- DROP FOREIGN TABLE remote_tbl; -- DROP FOREIGN TABLE insert_tbl; -- DROP TABLE base_tbl3; -- DROP TABLE base_tbl4; -- RESET enable_mergejoin; -- RESET enable_hashjoin; -- -- Test that UPDATE/DELETE with inherited target works with async_capable enabled -- EXPLAIN (VERBOSE, COSTS OFF) -- UPDATE async_pt SET c = c || c WHERE b = 0 RETURNING *; -- UPDATE async_pt SET c = c || c WHERE b = 0 RETURNING *; -- EXPLAIN (VERBOSE, COSTS OFF) -- DELETE FROM async_pt WHERE b = 0 RETURNING *; -- DELETE FROM async_pt WHERE b = 0 RETURNING *; -- -- Check EXPLAIN ANALYZE for a query that scans empty partitions asynchronously -- DELETE FROM async_p1; -- DELETE FROM async_p2; -- DELETE FROM async_p3; -- EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF) -- SELECT * FROM async_pt; -- -- Clean up -- DROP TABLE async_pt; -- DROP TABLE base_tbl1; -- DROP TABLE base_tbl2; -- DROP TABLE result_tbl; -- DROP TABLE join_tbl; -- ALTER SERVER loopback OPTIONS (DROP async_capable); -- ALTER SERVER loopback2 OPTIONS (DROP async_capable); -- Clean-up --Testcase 733: DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr; --Testcase 734: DROP USER MAPPING FOR CURRENT_USER SERVER sqlite_svr2; --Testcase 735: DROP SERVER sqlite_svr CASCADE; NOTICE: drop cascades to 122 other objects DETAIL: drop cascades to foreign table "S 1"."T 0" drop cascades to foreign table "S 1"."T 1" drop cascades to foreign table "S 1"."T 2" drop cascades to foreign table "S 1"."T 3" drop cascades to foreign table "S 1"."T 4" drop cascades to foreign table "S 1".base_tbl drop cascades to foreign table "S 1".loc1 drop cascades to foreign table "S 1".loct drop cascades to foreign table "S 1".loct1 drop cascades to foreign table "S 1".loct2 drop cascades to foreign table "S 1".loct3 drop cascades to foreign table "S 1".loct4 drop cascades to foreign table "S 1".loct4_2 drop cascades to foreign table "S 1".loct5 drop cascades to foreign table "S 1".loct6 drop cascades to foreign table "S 1".loct7 drop cascades to foreign table "S 1".local_tbl drop cascades to foreign table "S 1".ft3 drop cascades to foreign table "S 1".foreign_tbl drop cascades to foreign table "S 1".grem1 drop cascades to foreign table "S 1".t1_constraint drop cascades to foreign table "S 1".tru_rtable0 drop cascades to foreign table "S 1".tru_pk_table drop cascades to foreign table "S 1".tru_fk_table drop cascades to foreign table "S 1".tru_rtable_parent drop cascades to foreign table "S 1".tru_rtable_child drop cascades to foreign table "S 1".loct_empty drop cascades to foreign table "S 1".batch_table drop cascades to foreign table ft1_org drop cascades to foreign table ft2 drop cascades to foreign table ft4 drop cascades to foreign table ft5 drop cascades to foreign table ft_empty drop cascades to foreign table ft3 drop cascades to foreign table ft1 drop cascades to foreign table loc1 drop cascades to foreign table rem1 drop cascades to foreign table grem1 drop cascades to foreign table import_dest1."T 0" drop cascades to foreign table import_dest1."T 1" drop cascades to foreign table import_dest1."T 2" drop cascades to foreign table import_dest1."T 3" drop cascades to foreign table import_dest1."T 4" drop cascades to foreign table import_dest1.base_tbl drop cascades to foreign table import_dest1.loc1 drop cascades to foreign table import_dest1.loct drop cascades to foreign table import_dest1.loct1 drop cascades to foreign table import_dest1.loct2 drop cascades to foreign table import_dest1.loct3 drop cascades to foreign table import_dest1.loct4 drop cascades to foreign table import_dest1.loct4_2 drop cascades to foreign table import_dest1.loct5 drop cascades to foreign table import_dest1.loct6 drop cascades to foreign table import_dest1.loct7 drop cascades to foreign table import_dest1.local_tbl drop cascades to foreign table import_dest1.ft3 drop cascades to foreign table import_dest1.foreign_tbl drop cascades to foreign table import_dest1.grem1 drop cascades to foreign table import_dest1.t1_constraint drop cascades to foreign table import_dest1.tru_rtable0 drop cascades to foreign table import_dest1.tru_pk_table drop cascades to foreign table import_dest1.tru_fk_table drop cascades to foreign table import_dest1.tru_rtable_parent drop cascades to foreign table import_dest1.tru_rtable_child drop cascades to foreign table import_dest1.loct_empty drop cascades to foreign table import_dest1.batch_table drop cascades to foreign table import_dest2."T 0" drop cascades to foreign table import_dest2."T 1" drop cascades to foreign table import_dest2."T 2" drop cascades to foreign table import_dest2."T 3" drop cascades to foreign table import_dest2."T 4" drop cascades to foreign table import_dest2.base_tbl drop cascades to foreign table import_dest2.loc1 drop cascades to foreign table import_dest2.loct drop cascades to foreign table import_dest2.loct1 drop cascades to foreign table import_dest2.loct2 drop cascades to foreign table import_dest2.loct3 drop cascades to foreign table import_dest2.loct4 drop cascades to foreign table import_dest2.loct4_2 drop cascades to foreign table import_dest2.loct5 drop cascades to foreign table import_dest2.loct6 drop cascades to foreign table import_dest2.loct7 drop cascades to foreign table import_dest2.local_tbl drop cascades to foreign table import_dest2.ft3 drop cascades to foreign table import_dest2.foreign_tbl drop cascades to foreign table import_dest2.grem1 drop cascades to foreign table import_dest2.t1_constraint drop cascades to foreign table import_dest2.tru_rtable0 drop cascades to foreign table import_dest2.tru_pk_table drop cascades to foreign table import_dest2.tru_fk_table drop cascades to foreign table import_dest2.tru_rtable_parent drop cascades to foreign table import_dest2.tru_rtable_child drop cascades to foreign table import_dest2.loct_empty drop cascades to foreign table import_dest2.batch_table drop cascades to foreign table import_dest3."T 1" drop cascades to foreign table import_dest3.loct6 drop cascades to foreign table import_dest3."T 0" drop cascades to foreign table import_dest3."T 2" drop cascades to foreign table import_dest3."T 3" drop cascades to foreign table import_dest3."T 4" and 22 other objects (see server log for list) --Testcase 736: DROP SERVER sqlite_svr2 CASCADE; NOTICE: drop cascades to foreign table ft6 --Testcase 737: DROP EXTENSION sqlite_fdw CASCADE;