1 -- ===================================================================
3 -- ===================================================================
4 CREATE EXTENSION postgres_fdw;
5 CREATE SERVER testserver1 FOREIGN DATA WRAPPER postgres_fdw;
8 EXECUTE $$CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw
9 OPTIONS (dbname '$$||current_database()||$$',
10 port '$$||current_setting('port')||$$'
12 EXECUTE $$CREATE SERVER loopback2 FOREIGN DATA WRAPPER postgres_fdw
13 OPTIONS (dbname '$$||current_database()||$$',
14 port '$$||current_setting('port')||$$'
16 EXECUTE $$CREATE SERVER loopback3 FOREIGN DATA WRAPPER postgres_fdw
17 OPTIONS (dbname '$$||current_database()||$$',
18 port '$$||current_setting('port')||$$'
22 CREATE USER MAPPING FOR public SERVER testserver1
23 OPTIONS (user 'value', password 'value');
24 CREATE USER MAPPING FOR CURRENT_USER SERVER loopback;
25 CREATE USER MAPPING FOR CURRENT_USER SERVER loopback2;
26 CREATE USER MAPPING FOR public SERVER loopback3;
27 -- ===================================================================
28 -- create objects used through FDW loopback server
29 -- ===================================================================
30 CREATE TYPE user_enum AS ENUM ('foo', 'bar', 'buz');
32 CREATE TABLE "S 1"."T 1" (
41 CONSTRAINT t1_pkey PRIMARY KEY ("C 1")
43 CREATE TABLE "S 1"."T 2" (
46 CONSTRAINT t2_pkey PRIMARY KEY (c1)
48 CREATE TABLE "S 1"."T 3" (
52 CONSTRAINT t3_pkey PRIMARY KEY (c1)
54 CREATE TABLE "S 1"."T 4" (
58 CONSTRAINT t4_pkey PRIMARY KEY (c1)
60 -- Disable autovacuum for these tables to avoid unexpected effects of that
61 ALTER TABLE "S 1"."T 1" SET (autovacuum_enabled = 'false');
62 ALTER TABLE "S 1"."T 2" SET (autovacuum_enabled = 'false');
63 ALTER TABLE "S 1"."T 3" SET (autovacuum_enabled = 'false');
64 ALTER TABLE "S 1"."T 4" SET (autovacuum_enabled = 'false');
65 INSERT INTO "S 1"."T 1"
68 to_char(id, 'FM00000'),
69 '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval,
70 '1970-01-01'::timestamp + ((id % 100) || ' days')::interval,
74 FROM generate_series(1, 1000) id;
75 INSERT INTO "S 1"."T 2"
77 'AAA' || to_char(id, 'FM000')
78 FROM generate_series(1, 100) id;
79 INSERT INTO "S 1"."T 3"
82 'AAA' || to_char(id, 'FM000')
83 FROM generate_series(1, 100) id;
84 DELETE FROM "S 1"."T 3" WHERE c1 % 2 != 0; -- delete for outer join tests
85 INSERT INTO "S 1"."T 4"
88 'AAA' || to_char(id, 'FM000')
89 FROM generate_series(1, 100) id;
90 DELETE FROM "S 1"."T 4" WHERE c1 % 3 != 0; -- delete for outer join tests
95 -- ===================================================================
96 -- create foreign tables
97 -- ===================================================================
98 CREATE FOREIGN TABLE ft1 (
106 c7 char(10) default 'ft1',
109 ALTER FOREIGN TABLE ft1 DROP COLUMN c0;
110 CREATE FOREIGN TABLE ft2 (
118 c7 char(10) default 'ft2',
121 ALTER FOREIGN TABLE ft2 DROP COLUMN cx;
122 CREATE FOREIGN TABLE ft4 (
126 ) SERVER loopback OPTIONS (schema_name 'S 1', table_name 'T 3');
127 CREATE FOREIGN TABLE ft5 (
131 ) SERVER loopback OPTIONS (schema_name 'S 1', table_name 'T 4');
132 CREATE FOREIGN TABLE ft6 (
136 ) SERVER loopback2 OPTIONS (schema_name 'S 1', table_name 'T 4');
137 CREATE FOREIGN TABLE ft7 (
141 ) SERVER loopback3 OPTIONS (schema_name 'S 1', table_name 'T 4');
142 -- ===================================================================
143 -- tests for validator
144 -- ===================================================================
145 -- requiressl and some other parameters are omitted because
146 -- valid values for them depend on configure options
147 ALTER SERVER testserver1 OPTIONS (
148 use_remote_estimate 'false',
150 fdw_startup_cost '123.456',
151 fdw_tuple_cost '0.123',
153 connect_timeout 'value',
158 --client_encoding 'value',
159 application_name 'value',
160 --fallback_application_name 'value',
162 keepalives_idle 'value',
163 keepalives_interval 'value',
164 tcp_user_timeout 'value',
165 -- requiressl 'value',
166 sslcompression 'value',
172 --requirepeer 'value',
175 gssdelegation 'value'
176 --replication 'value'
178 -- Error, invalid list syntax
179 ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo; bar');
180 ERROR: parameter "extensions" must be a list of extension names
181 -- OK but gets a warning
182 ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo, bar');
183 WARNING: extension "foo" is not installed
184 WARNING: extension "bar" is not installed
185 ALTER SERVER testserver1 OPTIONS (DROP extensions);
186 ALTER USER MAPPING FOR public SERVER testserver1
187 OPTIONS (DROP user, DROP password);
188 -- Attempt to add a valid option that's not allowed in a user mapping
189 ALTER USER MAPPING FOR public SERVER testserver1
190 OPTIONS (ADD sslmode 'require');
191 ERROR: invalid option "sslmode"
192 -- But we can add valid ones fine
193 ALTER USER MAPPING FOR public SERVER testserver1
194 OPTIONS (ADD sslpassword 'dummy');
195 -- Ensure valid options we haven't used in a user mapping yet are
196 -- permitted to check validation.
197 ALTER USER MAPPING FOR public SERVER testserver1
198 OPTIONS (ADD sslkey 'value', ADD sslcert 'value');
199 ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name 'T 1');
200 ALTER FOREIGN TABLE ft2 OPTIONS (schema_name 'S 1', table_name 'T 1');
201 ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
202 ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
204 List of foreign tables
205 Schema | Table | Server | FDW options | Description
206 --------+-------+-----------+---------------------------------------+-------------
207 public | ft1 | loopback | (schema_name 'S 1', table_name 'T 1') |
208 public | ft2 | loopback | (schema_name 'S 1', table_name 'T 1') |
209 public | ft4 | loopback | (schema_name 'S 1', table_name 'T 3') |
210 public | ft5 | loopback | (schema_name 'S 1', table_name 'T 4') |
211 public | ft6 | loopback2 | (schema_name 'S 1', table_name 'T 4') |
212 public | ft7 | loopback3 | (schema_name 'S 1', table_name 'T 4') |
215 -- Test that alteration of server options causes reconnection
216 -- Remote's errors might be non-English, so hide them to ensure stable results
218 SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work
220 -------+------------------------------
221 00001 | Fri Jan 02 00:00:00 1970 PST
224 ALTER SERVER loopback OPTIONS (SET dbname 'no such database');
225 SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should fail
226 ERROR: could not connect to server "loopback"
229 EXECUTE $$ALTER SERVER loopback
230 OPTIONS (SET dbname '$$||current_database()||$$')$$;
233 SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work again
235 -------+------------------------------
236 00001 | Fri Jan 02 00:00:00 1970 PST
239 -- Test that alteration of user mapping options causes reconnection
240 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback
241 OPTIONS (ADD user 'no such user');
242 SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should fail
243 ERROR: could not connect to server "loopback"
244 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback
246 SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1; -- should work again
248 -------+------------------------------
249 00001 | Fri Jan 02 00:00:00 1970 PST
252 \set VERBOSITY default
253 -- Now we should be able to run ANALYZE.
254 -- To exercise multiple code paths, we use local stats on ft1
255 -- and remote-estimate mode on ft2.
257 ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true');
258 -- ===================================================================
259 -- test error case for create publication on foreign table
260 -- ===================================================================
261 CREATE PUBLICATION testpub_ftbl FOR TABLE ft1; -- should fail
262 ERROR: cannot add relation "ft1" to publication
263 DETAIL: This operation is not supported for foreign tables.
264 -- ===================================================================
266 -- ===================================================================
267 -- single table without alias
268 EXPLAIN (COSTS OFF) SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
270 ---------------------
274 SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
275 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
276 -----+----+-------+------------------------------+--------------------------+----+------------+-----
277 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
278 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
279 103 | 3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
280 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo
281 105 | 5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo
282 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo
283 107 | 7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
284 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
285 109 | 9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo
286 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo
289 -- single table with alias - also test that tableoid sort is not pushed to remote side
290 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
292 -------------------------------------------------------------------------------------
294 Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
296 Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
297 Sort Key: t1.c3, t1.c1, t1.tableoid
298 -> Foreign Scan on public.ft1 t1
299 Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
300 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
303 SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
304 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
305 -----+----+-------+------------------------------+--------------------------+----+------------+-----
306 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
307 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
308 103 | 3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
309 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo
310 105 | 5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo
311 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo
312 107 | 7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
313 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
314 109 | 9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo
315 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo
318 -- whole-row reference
319 EXPLAIN (VERBOSE, COSTS OFF) SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
321 --------------------------------------------------------------------------------------------------------------------------------------------------------------
322 Foreign Scan on public.ft1 t1
324 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" ORDER BY c3 ASC NULLS LAST, "C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 100::bigint
327 SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
329 --------------------------------------------------------------------------------------------
330 (101,1,00101,"Fri Jan 02 00:00:00 1970 PST","Fri Jan 02 00:00:00 1970",1,"1 ",foo)
331 (102,2,00102,"Sat Jan 03 00:00:00 1970 PST","Sat Jan 03 00:00:00 1970",2,"2 ",foo)
332 (103,3,00103,"Sun Jan 04 00:00:00 1970 PST","Sun Jan 04 00:00:00 1970",3,"3 ",foo)
333 (104,4,00104,"Mon Jan 05 00:00:00 1970 PST","Mon Jan 05 00:00:00 1970",4,"4 ",foo)
334 (105,5,00105,"Tue Jan 06 00:00:00 1970 PST","Tue Jan 06 00:00:00 1970",5,"5 ",foo)
335 (106,6,00106,"Wed Jan 07 00:00:00 1970 PST","Wed Jan 07 00:00:00 1970",6,"6 ",foo)
336 (107,7,00107,"Thu Jan 08 00:00:00 1970 PST","Thu Jan 08 00:00:00 1970",7,"7 ",foo)
337 (108,8,00108,"Fri Jan 09 00:00:00 1970 PST","Fri Jan 09 00:00:00 1970",8,"8 ",foo)
338 (109,9,00109,"Sat Jan 10 00:00:00 1970 PST","Sat Jan 10 00:00:00 1970",9,"9 ",foo)
339 (110,0,00110,"Sun Jan 11 00:00:00 1970 PST","Sun Jan 11 00:00:00 1970",0,"0 ",foo)
343 SELECT * FROM ft1 WHERE false;
344 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
345 ----+----+----+----+----+----+----+----
349 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1';
351 ----------------------------------------------------------------------------------------------------------------------------------
352 Foreign Scan on public.ft1 t1
353 Output: c1, c2, c3, c4, c5, c6, c7, c8
354 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c7 >= '1')) AND (("C 1" = 101)) AND ((c6 = '1'))
357 SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1';
358 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
359 -----+----+-------+------------------------------+--------------------------+----+------------+-----
360 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
363 -- with FOR UPDATE/SHARE
364 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE;
366 ----------------------------------------------------------------------------------------------------------
367 Foreign Scan on public.ft1 t1
368 Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
369 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 101)) FOR UPDATE
372 SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE;
373 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
374 -----+----+-------+------------------------------+--------------------------+----+------------+-----
375 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
378 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE;
380 ---------------------------------------------------------------------------------------------------------
381 Foreign Scan on public.ft1 t1
382 Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
383 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 102)) FOR SHARE
386 SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE;
387 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
388 -----+----+-------+------------------------------+--------------------------+----+------------+-----
389 102 | 2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
393 SELECT COUNT(*) FROM ft1 t1;
400 SELECT * FROM ft1 t1 WHERE t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 <= 10) ORDER BY c1;
401 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
402 ----+----+-------+------------------------------+--------------------------+----+------------+-----
403 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
404 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
405 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
406 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo
407 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo
408 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo
409 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
410 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
411 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo
412 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo
416 SELECT * FROM ft1 t1 WHERE t1.c3 = (SELECT MAX(c3) FROM ft2 t2) ORDER BY c1;
417 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
418 ------+----+-------+------------------------------+--------------------------+----+------------+-----
419 1000 | 0 | 01000 | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0 | 0 | foo
423 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;
425 ----+----+-------+------------------------------
426 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST
427 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST
428 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST
429 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST
430 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST
431 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST
432 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST
433 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST
434 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST
435 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST
439 SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1;
441 ----------+----------
445 -- Test forcing the remote server to produce sorted data for a merge join.
446 SET enable_hashjoin TO false;
447 SET enable_nestloop TO false;
448 -- inner join; expressions in the clauses appear in the equivalence class list
449 EXPLAIN (VERBOSE, COSTS OFF)
450 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;
452 ---------------------------------------------------------------------------------------
454 Output: t1.c1, t2."C 1"
456 Output: t1.c1, t2."C 1"
458 Merge Cond: (t1.c1 = t2."C 1")
459 -> Foreign Scan on public.ft2 t1
461 Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
462 -> Index Only Scan using t1_pkey on "S 1"."T 1" t2
466 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;
481 -- outer join; expressions in the clauses do not appear in equivalence class
482 -- list but no output change as compared to the previous query
483 EXPLAIN (VERBOSE, COSTS OFF)
484 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;
486 ---------------------------------------------------------------------------------------
488 Output: t1.c1, t2."C 1"
490 Output: t1.c1, t2."C 1"
492 Merge Cond: (t1.c1 = t2."C 1")
493 -> Foreign Scan on public.ft2 t1
495 Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
496 -> Index Only Scan using t1_pkey on "S 1"."T 1" t2
500 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;
515 -- A join between local table and foreign join. ORDER BY clause is added to the
516 -- foreign join so that the local table can be joined using merge join strategy.
517 EXPLAIN (VERBOSE, COSTS OFF)
518 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;
520 ---------------------------------------------------------------------------------------------------------------------------------------------------------
526 Merge Cond: (t3.c1 = t1."C 1")
529 Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
530 Remote SQL: SELECT r3."C 1" FROM ("S 1"."T 1" r2 INNER JOIN "S 1"."T 1" r3 ON (((r3."C 1" = r2."C 1")))) ORDER BY r2."C 1" ASC NULLS LAST
531 -> Index Only Scan using t1_pkey on "S 1"."T 1" t1
535 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;
550 -- Test similar to above, except that the full join prevents any equivalence
551 -- classes from being merged. This produces single relation equivalence classes
552 -- included in join restrictions.
553 EXPLAIN (VERBOSE, COSTS OFF)
554 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;
556 ------------------------------------------------------------------------------------------------------------------------------------------------------------------
558 Output: t1."C 1", t2.c1, t3.c1
560 Output: t1."C 1", t2.c1, t3.c1
562 Merge Cond: (t3.c1 = t1."C 1")
565 Relations: (public.ft2 t3) LEFT JOIN (public.ft1 t2)
566 Remote SQL: SELECT r3."C 1", r2."C 1" FROM ("S 1"."T 1" r3 LEFT JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r3."C 1")))) ORDER BY r3."C 1" ASC NULLS LAST
567 -> Index Only Scan using t1_pkey on "S 1"."T 1" t1
571 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;
586 -- Test similar to above with all full outer joins
587 EXPLAIN (VERBOSE, COSTS OFF)
588 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;
590 ------------------------------------------------------------------------------------------------------------------------------------------------------------------
592 Output: t1."C 1", t2.c1, t3.c1
594 Output: t1."C 1", t2.c1, t3.c1
596 Merge Cond: (t3.c1 = t1."C 1")
599 Relations: (public.ft1 t2) FULL JOIN (public.ft2 t3)
600 Remote SQL: SELECT r2."C 1", r3."C 1" FROM ("S 1"."T 1" r2 FULL JOIN "S 1"."T 1" r3 ON (((r2."C 1" = r3."C 1")))) ORDER BY r3."C 1" ASC NULLS LAST
601 -> Index Only Scan using t1_pkey on "S 1"."T 1" t1
605 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;
620 RESET enable_hashjoin;
621 RESET enable_nestloop;
622 -- Test executing assertion in estimate_path_cost_size() that makes sure that
623 -- retrieved_rows for foreign rel re-used to cost pre-sorted foreign paths is
624 -- a sensible value even when the rel has tuples=0
625 CREATE TABLE loct_empty (c1 int NOT NULL, c2 text);
626 CREATE FOREIGN TABLE ft_empty (c1 int NOT NULL, c2 text)
627 SERVER loopback OPTIONS (table_name 'loct_empty');
628 INSERT INTO loct_empty
629 SELECT id, 'AAA' || to_char(id, 'FM000') FROM generate_series(1, 100) id;
630 DELETE FROM loct_empty;
632 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft_empty ORDER BY c1;
634 -------------------------------------------------------------------------------
635 Foreign Scan on public.ft_empty
637 Remote SQL: SELECT c1, c2 FROM public.loct_empty ORDER BY c1 ASC NULLS LAST
640 -- ===================================================================
641 -- WHERE with remotely-executable conditions
642 -- ===================================================================
643 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 1; -- Var, OpExpr(b), Const
645 ---------------------------------------------------------------------------------------------
646 Foreign Scan on public.ft1 t1
647 Output: c1, c2, c3, c4, c5, c6, c7, c8
648 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
651 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 100 AND t1.c2 = 0; -- BoolExpr
653 --------------------------------------------------------------------------------------------------------------
654 Foreign Scan on public.ft1 t1
655 Output: c1, c2, c3, c4, c5, c6, c7, c8
656 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 100)) AND ((c2 = 0))
659 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c3 IS NULL; -- NullTest
661 ----------------------------------------------------------------------------------------------
662 Foreign Scan on public.ft1 t1
663 Output: c1, c2, c3, c4, c5, c6, c7, c8
664 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c3 IS NULL))
667 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c3 IS NOT NULL; -- NullTest
669 --------------------------------------------------------------------------------------------------
670 Foreign Scan on public.ft1 t1
671 Output: c1, c2, c3, c4, c5, c6, c7, c8
672 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c3 IS NOT NULL))
675 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr
677 ---------------------------------------------------------------------------------------------------------------------
678 Foreign Scan on public.ft1 t1
679 Output: c1, c2, c3, c4, c5, c6, c7, c8
680 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((round(abs("C 1"), 0) = 1::numeric))
683 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1; -- OpExpr(l)
685 -----------------------------------------------------------------------------------------------------
686 Foreign Scan on public.ft1 t1
687 Output: c1, c2, c3, c4, c5, c6, c7, c8
688 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = (- "C 1")))
691 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
693 --------------------------------------------------------------------------------------------------------------------------------------------
694 Foreign Scan on public.ft1 t1
695 Output: c1, c2, c3, c4, c5, c6, c7, c8
696 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((("C 1" IS NOT NULL) IS DISTINCT FROM ("C 1" IS NOT NULL)))
699 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr
701 ---------------------------------------------------------------------------------------------------------------------------
702 Foreign Scan on public.ft1 t1
703 Output: c1, c2, c3, c4, c5, c6, c7, c8
704 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = ANY (ARRAY[c2, 1, ("C 1" + 0)])))
707 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- SubscriptingRef
709 ----------------------------------------------------------------------------------------------------------------------
710 Foreign Scan on public.ft1 t1
711 Output: c1, c2, c3, c4, c5, c6, c7, c8
712 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = ((ARRAY["C 1", c2, 3])[1])))
715 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar'; -- check special chars
717 -------------------------------------------------------------------------------------------------------
718 Foreign Scan on public.ft1 t1
719 Output: c1, c2, c3, c4, c5, c6, c7, c8
720 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c6 = E'foo''s\\bar'))
723 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c8 = 'foo'; -- can't be sent to remote
725 -------------------------------------------------------------------------
726 Foreign Scan on public.ft1 t1
727 Output: c1, c2, c3, c4, c5, c6, c7, c8
728 Filter: (t1.c8 = 'foo'::user_enum)
729 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
732 -- parameterized remote path for foreign table
733 EXPLAIN (VERBOSE, COSTS OFF)
734 SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2;
736 -------------------------------------------------------------------------------------------------------------
738 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
739 -> Index Scan using t1_pkey on "S 1"."T 1" a
740 Output: a."C 1", a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8
741 Index Cond: (a."C 1" = 47)
742 -> Foreign Scan on public.ft2 b
743 Output: b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8
744 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
747 SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2;
748 C 1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
749 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----
750 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
753 -- check both safe and unsafe join conditions
754 EXPLAIN (VERBOSE, COSTS OFF)
755 SELECT * FROM ft2 a, ft2 b
756 WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7);
758 -------------------------------------------------------------------------------------------------------------
760 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
761 -> Foreign Scan on public.ft2 a
762 Output: a.c1, a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8
763 Filter: (a.c8 = 'foo'::user_enum)
764 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c2 = 6))
765 -> Foreign Scan on public.ft2 b
766 Output: b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8
767 Filter: ((b.c7)::text = upper((a.c7)::text))
768 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
771 SELECT * FROM ft2 a, ft2 b
772 WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7);
773 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
774 -----+----+-------+------------------------------+--------------------------+----+------------+-----+-----+----+-------+------------------------------+--------------------------+----+------------+-----
775 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
776 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
777 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
778 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
779 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
780 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
781 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
782 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
783 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
784 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
785 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
786 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
787 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
788 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
789 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
790 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
791 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
792 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
793 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
794 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
795 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
796 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
797 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
798 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
799 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
800 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
801 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
802 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
803 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
804 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
805 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
806 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
807 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
808 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
809 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
810 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
811 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
812 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
813 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
814 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
815 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
816 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
817 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
818 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
819 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
820 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
821 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
822 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
823 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
824 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
825 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
826 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
827 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
828 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
829 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
830 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
831 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
832 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
833 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
834 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
835 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
836 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
837 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
838 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
839 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
840 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
841 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
842 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
843 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
844 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
845 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
846 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
847 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
848 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
849 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
850 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
851 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
852 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
853 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
854 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
855 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
856 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
857 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
858 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
859 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
860 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
861 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
862 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
863 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
864 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
865 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
866 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
867 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
868 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
869 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
870 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
871 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
872 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
873 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
874 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
877 -- bug before 9.3.5 due to sloppy handling of remote-estimate parameters
878 SELECT * FROM ft1 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft2 WHERE c1 < 5));
879 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
880 ----+----+-------+------------------------------+--------------------------+----+------------+-----
881 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
882 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
883 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
884 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo
887 SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5));
888 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
889 ----+----+-------+------------------------------+--------------------------+----+------------+-----
890 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
891 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
892 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
893 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo
896 -- user-defined operator/function
897 CREATE FUNCTION postgres_fdw_abs(int) RETURNS int AS $$
901 $$ LANGUAGE plpgsql IMMUTABLE;
902 CREATE OPERATOR === (
908 -- built-in operators and functions can be shipped for remote execution
909 EXPLAIN (VERBOSE, COSTS OFF)
910 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
912 ---------------------------------------------------------------------------
915 Relations: Aggregate on (public.ft1 t1)
916 Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" = abs(c2)))
919 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
925 EXPLAIN (VERBOSE, COSTS OFF)
926 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
928 ----------------------------------------------------------------------
931 Relations: Aggregate on (public.ft1 t1)
932 Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" = c2))
935 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
941 -- by default, user-defined ones cannot
942 EXPLAIN (VERBOSE, COSTS OFF)
943 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
945 -----------------------------------------------------------
948 -> Foreign Scan on public.ft1 t1
950 Filter: (t1.c1 = postgres_fdw_abs(t1.c2))
951 Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
954 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
960 EXPLAIN (VERBOSE, COSTS OFF)
961 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
963 -----------------------------------------------------------
966 -> Foreign Scan on public.ft1 t1
968 Filter: (t1.c1 === t1.c2)
969 Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
972 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
978 -- ORDER BY can be shipped, though
979 EXPLAIN (VERBOSE, COSTS OFF)
980 SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1;
982 ----------------------------------------------------------------------------------------------------------
984 Output: c1, c2, c3, c4, c5, c6, c7, c8
985 -> Foreign Scan on public.ft1 t1
986 Output: c1, c2, c3, c4, c5, c6, c7, c8
987 Filter: (t1.c1 === t1.c2)
988 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
991 SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1;
992 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
993 ----+----+-------+------------------------------+--------------------------+----+------------+-----
994 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
997 -- but let's put them in an extension ...
998 ALTER EXTENSION postgres_fdw ADD FUNCTION postgres_fdw_abs(int);
999 ALTER EXTENSION postgres_fdw ADD OPERATOR === (int, int);
1000 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
1001 -- ... now they can be shipped
1002 EXPLAIN (VERBOSE, COSTS OFF)
1003 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
1005 -----------------------------------------------------------------------------------------------
1008 Relations: Aggregate on (public.ft1 t1)
1009 Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" = public.postgres_fdw_abs(c2)))
1012 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
1018 EXPLAIN (VERBOSE, COSTS OFF)
1019 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
1021 -----------------------------------------------------------------------------------------
1024 Relations: Aggregate on (public.ft1 t1)
1025 Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2))
1028 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
1034 -- and both ORDER BY and LIMIT can be shipped
1035 EXPLAIN (VERBOSE, COSTS OFF)
1036 SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1;
1038 ------------------------------------------------------------------------------------------------------------------------------------------------------------
1039 Foreign Scan on public.ft1 t1
1040 Output: c1, c2, c3, c4, c5, c6, c7, c8
1041 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2)) ORDER BY c2 ASC NULLS LAST LIMIT 1::bigint
1044 SELECT * FROM ft1 t1 WHERE t1.c1 === t1.c2 order by t1.c2 limit 1;
1045 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
1046 ----+----+-------+------------------------------+--------------------------+----+------------+-----
1047 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
1050 -- Ensure we don't ship FETCH FIRST .. WITH TIES
1051 EXPLAIN (VERBOSE, COSTS OFF)
1052 SELECT t1.c2 FROM ft1 t1 WHERE t1.c1 > 960 ORDER BY t1.c2 FETCH FIRST 2 ROWS WITH TIES;
1054 -------------------------------------------------------------------------------------------------
1057 -> Foreign Scan on public.ft1 t1
1059 Remote SQL: SELECT c2 FROM "S 1"."T 1" WHERE (("C 1" > 960)) ORDER BY c2 ASC NULLS LAST
1062 SELECT t1.c2 FROM ft1 t1 WHERE t1.c1 > 960 ORDER BY t1.c2 FETCH FIRST 2 ROWS WITH TIES;
1071 -- Test CASE pushdown
1072 EXPLAIN (VERBOSE, COSTS OFF)
1073 SELECT c1,c2,c3 FROM ft2 WHERE CASE WHEN c1 > 990 THEN c1 END < 1000 ORDER BY c1;
1075 ----------------------------------------------------------------------------------------------------------------------------------------------------------------
1076 Foreign Scan on public.ft2
1078 Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1" WHERE (((CASE WHEN ("C 1" > 990) THEN "C 1" ELSE NULL::integer END) < 1000)) ORDER BY "C 1" ASC NULLS LAST
1081 SELECT c1,c2,c3 FROM ft2 WHERE CASE WHEN c1 > 990 THEN c1 END < 1000 ORDER BY c1;
1096 EXPLAIN (VERBOSE, COSTS OFF)
1097 SELECT c1,c2,c3 FROM ft2 WHERE CASE CASE WHEN c2 > 0 THEN c2 END WHEN 100 THEN 601 WHEN c2 THEN c2 ELSE 0 END > 600 ORDER BY c1;
1099 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1100 Foreign Scan on public.ft2
1102 Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1" WHERE (((CASE (CASE WHEN (c2 > 0) THEN c2 ELSE NULL::integer END) WHEN 100 THEN 601 WHEN c2 THEN c2 ELSE 0 END) > 600)) ORDER BY "C 1" ASC NULLS LAST
1105 SELECT c1,c2,c3 FROM ft2 WHERE CASE CASE WHEN c2 > 0 THEN c2 END WHEN 100 THEN 601 WHEN c2 THEN c2 ELSE 0 END > 600 ORDER BY c1;
1111 EXPLAIN (VERBOSE, COSTS OFF)
1112 SELECT * FROM ft1 WHERE c1 > (CASE mod(c1, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END);
1114 ----------------------------------------------------------------------------------------------------------------------------------------------------------
1115 Foreign Scan on public.ft1
1116 Output: c1, c2, c3, c4, c5, c6, c7, c8
1117 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" > (CASE mod("C 1", 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END)))
1120 -- CASE cannot be pushed down because of unshippable arg clause
1121 EXPLAIN (VERBOSE, COSTS OFF)
1122 SELECT * FROM ft1 WHERE c1 > (CASE random()::integer WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END);
1124 -----------------------------------------------------------------------------------------
1125 Foreign Scan on public.ft1
1126 Output: c1, c2, c3, c4, c5, c6, c7, c8
1127 Filter: (ft1.c1 > CASE (random())::integer WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END)
1128 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1131 -- these are shippable
1132 EXPLAIN (VERBOSE, COSTS OFF)
1133 SELECT * FROM ft1 WHERE CASE c6 WHEN 'foo' THEN true ELSE c3 < 'bar' END;
1135 --------------------------------------------------------------------------------------------------------------------------------------------
1136 Foreign Scan on public.ft1
1137 Output: c1, c2, c3, c4, c5, c6, c7, c8
1138 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((CASE c6 WHEN 'foo'::text THEN true ELSE (c3 < 'bar') END))
1141 EXPLAIN (VERBOSE, COSTS OFF)
1142 SELECT * FROM ft1 WHERE CASE c3 WHEN c6 THEN true ELSE c3 < 'bar' END;
1144 -----------------------------------------------------------------------------------------------------------------------------------
1145 Foreign Scan on public.ft1
1146 Output: c1, c2, c3, c4, c5, c6, c7, c8
1147 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((CASE c3 WHEN c6 THEN true ELSE (c3 < 'bar') END))
1150 -- but this is not because of collation
1151 EXPLAIN (VERBOSE, COSTS OFF)
1152 SELECT * FROM ft1 WHERE CASE c3 COLLATE "C" WHEN c6 THEN true ELSE c3 < 'bar' END;
1154 -------------------------------------------------------------------------------------
1155 Foreign Scan on public.ft1
1156 Output: c1, c2, c3, c4, c5, c6, c7, c8
1157 Filter: CASE (ft1.c3)::text WHEN ft1.c6 THEN true ELSE (ft1.c3 < 'bar'::text) END
1158 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1161 -- a regconfig constant referring to this text search configuration
1162 -- is initially unshippable
1163 CREATE TEXT SEARCH CONFIGURATION public.custom_search
1164 (COPY = pg_catalog.english);
1165 EXPLAIN (VERBOSE, COSTS OFF)
1166 SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1
1167 WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0;
1169 -------------------------------------------------------------------------
1170 Foreign Scan on public.ft1
1171 Output: c1, to_tsvector('custom_search'::regconfig, c3)
1172 Filter: (length(to_tsvector('custom_search'::regconfig, ft1.c3)) > 0)
1173 Remote SQL: SELECT "C 1", c3 FROM "S 1"."T 1" WHERE (("C 1" = 642))
1176 SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1
1177 WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0;
1183 -- but if it's in a shippable extension, it can be shipped
1184 ALTER EXTENSION postgres_fdw ADD TEXT SEARCH CONFIGURATION public.custom_search;
1185 -- however, that doesn't flush the shippability cache, so do a quick reconnect
1187 EXPLAIN (VERBOSE, COSTS OFF)
1188 SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1
1189 WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0;
1191 ----------------------------------------------------------------------------------------------------------------------------------------------
1192 Foreign Scan on public.ft1
1193 Output: c1, to_tsvector('custom_search'::regconfig, c3)
1194 Remote SQL: SELECT "C 1", c3 FROM "S 1"."T 1" WHERE (("C 1" = 642)) AND ((length(to_tsvector('public.custom_search'::regconfig, c3)) > 0))
1197 SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1
1198 WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0;
1204 -- ===================================================================
1206 -- ===================================================================
1207 -- we should not push order by clause with volatile expressions or unsafe
1209 EXPLAIN (VERBOSE, COSTS OFF)
1210 SELECT * FROM ft2 ORDER BY ft2.c1, random();
1212 -------------------------------------------------------------------------------
1214 Output: c1, c2, c3, c4, c5, c6, c7, c8, (random())
1215 Sort Key: ft2.c1, (random())
1216 -> Foreign Scan on public.ft2
1217 Output: c1, c2, c3, c4, c5, c6, c7, c8, random()
1218 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1221 EXPLAIN (VERBOSE, COSTS OFF)
1222 SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C";
1224 -------------------------------------------------------------------------------
1226 Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text)
1227 Sort Key: ft2.c1, ft2.c3 COLLATE "C"
1228 -> Foreign Scan on public.ft2
1229 Output: c1, c2, c3, c4, c5, c6, c7, c8, c3
1230 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1233 -- Ensure we don't push ORDER BY expressions which are Consts at the UNION
1234 -- child level to the foreign server.
1235 EXPLAIN (VERBOSE, COSTS OFF)
1237 SELECT 1 AS type,c1 FROM ft1
1239 SELECT 2 AS type,c1 FROM ft2
1240 ) a ORDER BY type,c1;
1242 ---------------------------------------------------------------------------------
1244 Sort Key: (1), ft1.c1
1245 -> Foreign Scan on public.ft1
1247 Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1248 -> Foreign Scan on public.ft2
1250 Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1253 EXPLAIN (VERBOSE, COSTS OFF)
1255 SELECT 1 AS type,c1 FROM ft1
1257 SELECT 2 AS type,c1 FROM ft2
1260 ---------------------------------------------------
1263 -> Foreign Scan on public.ft1
1265 Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
1266 -> Foreign Scan on public.ft2
1268 Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
1271 -- ===================================================================
1273 -- ===================================================================
1274 -- Analyze ft4 and ft5 so that we have better statistics. These tables do not
1275 -- have use_remote_estimate set.
1279 EXPLAIN (VERBOSE, COSTS OFF)
1280 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;
1282 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1284 Output: t1.c1, t2.c1, t1.c3
1285 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1286 Remote SQL: SELECT r1."C 1", r2."C 1", r1.c3 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 100::bigint
1289 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;
1304 -- join three tables
1305 EXPLAIN (VERBOSE, COSTS OFF)
1306 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;
1308 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1310 Output: t1.c1, t2.c2, t3.c3, t1.c3
1311 Relations: ((public.ft1 t1) INNER JOIN (public.ft2 t2)) INNER JOIN (public.ft4 t3)
1312 Remote SQL: SELECT r1."C 1", r2.c2, r4.c3, r1.c3 FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")))) INNER JOIN "S 1"."T 3" r4 ON (((r1."C 1" = r4.c1)))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 10::bigint
1315 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;
1331 EXPLAIN (VERBOSE, COSTS OFF)
1332 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;
1334 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1336 Output: t1.c1, t2.c1
1337 Relations: (public.ft4 t1) LEFT JOIN (public.ft5 t2)
1338 Remote SQL: SELECT r1.c1, r2.c1 FROM ("S 1"."T 3" r1 LEFT JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) ORDER BY r1.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST LIMIT 10::bigint OFFSET 10::bigint
1341 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;
1356 -- left outer join three tables
1357 EXPLAIN (VERBOSE, COSTS OFF)
1358 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;
1360 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1362 Output: t1.c1, t2.c2, t3.c3
1363 Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
1364 Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 LEFT JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) LEFT JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1)))) LIMIT 10::bigint OFFSET 10::bigint
1367 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;
1382 -- left outer join + placement of clauses.
1383 -- clauses within the nullable side are not pulled up, but top level clause on
1384 -- non-nullable side is pushed into non-nullable side
1385 EXPLAIN (VERBOSE, COSTS OFF)
1386 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;
1388 ---------------------------------------------------------------------------------------------------------------------------------------------------------------
1390 Output: t1.c1, t1.c2, ft5.c1, ft5.c2
1391 Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
1392 Remote SQL: SELECT r1.c1, r1.c2, r4.c1, r4.c2 FROM ("S 1"."T 3" r1 LEFT JOIN "S 1"."T 4" r4 ON (((r1.c1 = r4.c1)) AND ((r4.c1 < 10)))) WHERE ((r1.c1 < 10))
1395 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;
1404 -- clauses within the nullable side are not pulled up, but the top level clause
1405 -- on nullable side is not pushed down into nullable side
1406 EXPLAIN (VERBOSE, COSTS OFF)
1407 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)
1408 WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
1410 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1412 Output: t1.c1, t1.c2, ft5.c1, ft5.c2
1413 Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
1414 Remote SQL: SELECT r1.c1, r1.c2, r4.c1, r4.c2 FROM ("S 1"."T 3" r1 LEFT JOIN "S 1"."T 4" r4 ON (((r1.c1 = r4.c1)) AND ((r4.c1 < 10)))) WHERE (((r4.c1 < 10) OR (r4.c1 IS NULL))) AND ((r1.c1 < 10))
1417 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)
1418 WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
1428 EXPLAIN (VERBOSE, COSTS OFF)
1429 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;
1431 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1433 Output: t1.c1, t2.c1
1434 Relations: (public.ft4 t2) LEFT JOIN (public.ft5 t1)
1435 Remote SQL: SELECT r1.c1, r2.c1 FROM ("S 1"."T 3" r2 LEFT JOIN "S 1"."T 4" r1 ON (((r1.c1 = r2.c1)))) ORDER BY r2.c1 ASC NULLS LAST, r1.c1 ASC NULLS LAST LIMIT 10::bigint OFFSET 10::bigint
1438 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;
1453 -- right outer join three tables
1454 EXPLAIN (VERBOSE, COSTS OFF)
1455 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;
1457 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1459 Output: t1.c1, t2.c2, t3.c3
1460 Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
1461 Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 3" r4 LEFT JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r4.c1)))) LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1")))) LIMIT 10::bigint OFFSET 10::bigint
1464 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;
1480 EXPLAIN (VERBOSE, COSTS OFF)
1481 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;
1483 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1485 Output: t1.c1, t2.c1
1486 Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
1487 Remote SQL: SELECT r1.c1, r2.c1 FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) ORDER BY r1.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST LIMIT 10::bigint OFFSET 45::bigint
1490 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;
1505 -- full outer join with restrictions on the joining relations
1506 -- a. the joining relations are both base relations
1507 EXPLAIN (VERBOSE, COSTS OFF)
1508 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;
1510 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1512 Output: ft4.c1, ft5.c1
1513 Relations: (public.ft4) FULL JOIN (public.ft5)
1514 Remote SQL: SELECT s4.c1, s5.c1 FROM ((SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s4(c1) FULL JOIN (SELECT c1 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s5(c1) ON (((s4.c1 = s5.c1)))) ORDER BY s4.c1 ASC NULLS LAST, s5.c1 ASC NULLS LAST
1517 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;
1530 EXPLAIN (VERBOSE, COSTS OFF)
1531 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;
1533 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1536 Relations: (public.ft4) FULL JOIN (public.ft5)
1537 Remote SQL: SELECT NULL FROM ((SELECT NULL FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s4 FULL JOIN (SELECT NULL FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s5 ON (TRUE)) LIMIT 10::bigint OFFSET 10::bigint
1540 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;
1555 -- b. one of the joining relations is a base relation and the other is a join
1557 EXPLAIN (VERBOSE, COSTS OFF)
1558 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;
1560 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1562 Output: ft4.c1, t2.c1, t3.c1
1563 Relations: (public.ft4) FULL JOIN ((public.ft4 t2) LEFT JOIN (public.ft5 t3))
1564 Remote SQL: SELECT s4.c1, s8.c1, s8.c2 FROM ((SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s4(c1) FULL JOIN (SELECT r5.c1, r6.c1 FROM ("S 1"."T 3" r5 LEFT JOIN "S 1"."T 4" r6 ON (((r5.c1 = r6.c1)))) WHERE ((r5.c1 >= 50)) AND ((r5.c1 <= 60))) s8(c1, c2) ON (((s4.c1 = s8.c1)))) ORDER BY s4.c1 ASC NULLS LAST, s8.c1 ASC NULLS LAST, s8.c2 ASC NULLS LAST
1567 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;
1578 -- c. test deparsing the remote query as nested subqueries
1579 EXPLAIN (VERBOSE, COSTS OFF)
1580 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;
1582 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1584 Output: ft4.c1, ft4_1.c1, ft5.c1
1585 Relations: (public.ft4) FULL JOIN ((public.ft4 ft4_1) FULL JOIN (public.ft5))
1586 Remote SQL: SELECT s4.c1, s10.c1, s10.c2 FROM ((SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s4(c1) FULL JOIN (SELECT s8.c1, s9.c1 FROM ((SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s8(c1) FULL JOIN (SELECT c1 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s9(c1) ON (((s8.c1 = s9.c1)))) WHERE (((s8.c1 IS NULL) OR (s8.c1 IS NOT NULL)))) s10(c1, c2) ON (((s4.c1 = s10.c1)))) ORDER BY s4.c1 ASC NULLS LAST, s10.c1 ASC NULLS LAST, s10.c2 ASC NULLS LAST
1589 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;
1602 -- d. test deparsing rowmarked relations as subqueries
1603 EXPLAIN (VERBOSE, COSTS OFF)
1604 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;
1606 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1608 Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".ctid, ft4.*, ft5.*
1610 Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".ctid, ft4.*, ft5.*
1612 Output: ft4.c1, ft4.*, ft5.c1, ft5.*
1613 Relations: (public.ft4) FULL JOIN (public.ft5)
1614 Remote SQL: SELECT s8.c1, s8.c2, s9.c1, s9.c2 FROM ((SELECT c1, ROW(c1, c2, c3) FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s8(c1, c2) FULL JOIN (SELECT c1, ROW(c1, c2, c3) FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s9(c1, c2) ON (((s8.c1 = s9.c1)))) WHERE (((s8.c1 IS NULL) OR (s8.c1 IS NOT NULL))) ORDER BY s8.c1 ASC NULLS LAST, s9.c1 ASC NULLS LAST
1616 Output: ft4.c1, ft4.*, ft5.c1, ft5.*
1617 Sort Key: ft4.c1, ft5.c1
1619 Output: ft4.c1, ft4.*, ft5.c1, ft5.*
1620 Hash Cond: (ft4.c1 = ft5.c1)
1621 Filter: ((ft4.c1 IS NULL) OR (ft4.c1 IS NOT NULL))
1622 -> Foreign Scan on public.ft4
1623 Output: ft4.c1, ft4.*
1624 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))
1626 Output: ft5.c1, ft5.*
1627 -> Foreign Scan on public.ft5
1628 Output: ft5.c1, ft5.*
1629 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))
1631 Output: "T 3".c1, "T 3".ctid
1632 -> Seq Scan on "S 1"."T 3"
1633 Output: "T 3".c1, "T 3".ctid
1634 Filter: ("T 3".c1 = 50)
1637 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;
1650 -- full outer join + inner join
1651 EXPLAIN (VERBOSE, COSTS OFF)
1652 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;
1654 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1656 Output: t1.c1, t2.c1, t3.c1
1657 Relations: ((public.ft4 t1) INNER JOIN (public.ft5 t2)) FULL JOIN (public.ft4 t3)
1658 Remote SQL: SELECT r1.c1, r2.c1, r4.c1 FROM (("S 1"."T 3" r1 INNER JOIN "S 1"."T 4" r2 ON (((r1.c1 = (r2.c1 + 1))) AND ((r1.c1 >= 50)) AND ((r1.c1 <= 60)))) FULL JOIN "S 1"."T 3" r4 ON (((r2.c1 = r4.c1)))) ORDER BY r1.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST, r4.c1 ASC NULLS LAST LIMIT 10::bigint
1661 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;
1676 -- full outer join three tables
1677 EXPLAIN (VERBOSE, COSTS OFF)
1678 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;
1680 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1682 Output: t1.c1, t2.c2, t3.c3
1683 Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
1684 Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) FULL JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1)))) LIMIT 10::bigint OFFSET 10::bigint
1687 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;
1702 -- full outer join + right outer join
1703 EXPLAIN (VERBOSE, COSTS OFF)
1704 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;
1706 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1708 Output: t1.c1, t2.c2, t3.c3
1709 Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
1710 Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 3" r4 LEFT JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r4.c1)))) LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1")))) LIMIT 10::bigint OFFSET 10::bigint
1713 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;
1728 -- right outer join + full outer join
1729 EXPLAIN (VERBOSE, COSTS OFF)
1730 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;
1732 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1734 Output: t1.c1, t2.c2, t3.c3
1735 Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) FULL JOIN (public.ft4 t3)
1736 Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r2 LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1")))) FULL JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1)))) LIMIT 10::bigint OFFSET 10::bigint
1739 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;
1754 -- full outer join + left outer join
1755 EXPLAIN (VERBOSE, COSTS OFF)
1756 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;
1758 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1760 Output: t1.c1, t2.c2, t3.c3
1761 Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
1762 Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) LEFT JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1)))) LIMIT 10::bigint OFFSET 10::bigint
1765 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;
1780 -- left outer join + full outer join
1781 EXPLAIN (VERBOSE, COSTS OFF)
1782 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;
1784 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1786 Output: t1.c1, t2.c2, t3.c3
1787 Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
1788 Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r1 LEFT JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) FULL JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1)))) LIMIT 10::bigint OFFSET 10::bigint
1791 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;
1806 SET enable_memoize TO off;
1807 -- right outer join + left outer join
1808 EXPLAIN (VERBOSE, COSTS OFF)
1809 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;
1811 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1813 Output: t1.c1, t2.c2, t3.c3
1814 Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) LEFT JOIN (public.ft4 t3)
1815 Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM (("S 1"."T 1" r2 LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1")))) LEFT JOIN "S 1"."T 3" r4 ON (((r2."C 1" = r4.c1)))) LIMIT 10::bigint OFFSET 10::bigint
1818 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;
1833 RESET enable_memoize;
1834 -- left outer join + right outer join
1835 EXPLAIN (VERBOSE, COSTS OFF)
1836 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;
1838 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1840 Output: t1.c1, t2.c2, t3.c3
1841 Relations: (public.ft4 t3) LEFT JOIN ((public.ft2 t1) INNER JOIN (public.ft2 t2))
1842 Remote SQL: SELECT r1."C 1", r2.c2, r4.c3 FROM ("S 1"."T 3" r4 LEFT JOIN ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) ON (((r2."C 1" = r4.c1)))) LIMIT 10::bigint OFFSET 10::bigint
1845 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;
1860 -- full outer join + WHERE clause, only matched rows
1861 EXPLAIN (VERBOSE, COSTS OFF)
1862 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;
1864 ------------------------------------------------------------------------------------------------------------------------------------------------------------------
1866 Output: t1.c1, t2.c1
1868 Output: t1.c1, t2.c1
1869 Sort Key: t1.c1, t2.c1
1871 Output: t1.c1, t2.c1
1872 Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
1873 Remote SQL: SELECT r1.c1, r2.c1 FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 = r2.c1) OR (r1.c1 IS NULL)))
1876 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;
1891 -- full outer join + WHERE clause with shippable extensions set
1892 EXPLAIN (VERBOSE, COSTS OFF)
1893 SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE postgres_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10;
1895 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1897 Output: t1.c1, t2.c2, t1.c3
1898 Relations: (public.ft1 t1) FULL JOIN (public.ft2 t2)
1899 Remote SQL: SELECT r1."C 1", r2.c2, r1.c3 FROM ("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) WHERE ((public.postgres_fdw_abs(r1."C 1") > 0)) LIMIT 10::bigint OFFSET 10::bigint
1902 ALTER SERVER loopback OPTIONS (DROP extensions);
1903 -- full outer join + WHERE clause with shippable extensions not set
1904 EXPLAIN (VERBOSE, COSTS OFF)
1905 SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE postgres_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10;
1907 -------------------------------------------------------------------------------------------------------------------------------
1909 Output: t1.c1, t2.c2, t1.c3
1911 Output: t1.c1, t2.c2, t1.c3
1912 Filter: (postgres_fdw_abs(t1.c1) > 0)
1913 Relations: (public.ft1 t1) FULL JOIN (public.ft2 t2)
1914 Remote SQL: SELECT r1."C 1", r2.c2, r1.c3 FROM ("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
1917 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
1918 -- join two tables with FOR UPDATE clause
1919 -- tests whole-row reference for row marks
1920 EXPLAIN (VERBOSE, COSTS OFF)
1921 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;
1923 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1925 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1926 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1927 Remote SQL: SELECT r1."C 1", r2."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 100::bigint FOR UPDATE OF r1
1930 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;
1945 EXPLAIN (VERBOSE, COSTS OFF)
1946 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;
1948 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1950 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1951 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1952 Remote SQL: SELECT r1."C 1", r2."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 100::bigint FOR UPDATE OF r1 FOR UPDATE OF r2
1955 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;
1970 -- join two tables with FOR SHARE clause
1971 EXPLAIN (VERBOSE, COSTS OFF)
1972 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;
1974 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1976 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1977 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1978 Remote SQL: SELECT r1."C 1", r2."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 100::bigint FOR SHARE OF r1
1981 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;
1996 EXPLAIN (VERBOSE, COSTS OFF)
1997 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;
1999 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2001 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
2002 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2003 Remote SQL: SELECT r1."C 1", r2."C 1", r1.c3, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 100::bigint FOR SHARE OF r1 FOR SHARE OF r2
2006 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;
2022 EXPLAIN (VERBOSE, COSTS OFF)
2023 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;
2025 -------------------------------------------------------------------------------------------------------------------------------------
2027 Output: t.c1_1, t.c2_1, t.c1_3
2030 Output: t1.c1, t1.c3, t2.c1
2031 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2032 Remote SQL: SELECT r1."C 1", r1.c3, r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1"))))
2034 Output: t.c1_1, t.c2_1, t.c1_3
2035 Sort Key: t.c1_3, t.c1_1
2037 Output: t.c1_1, t.c2_1, t.c1_3
2040 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;
2055 -- ctid with whole-row reference
2056 EXPLAIN (VERBOSE, COSTS OFF)
2057 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;
2059 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2061 Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
2062 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2063 Remote SQL: SELECT r1.ctid, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END, r1."C 1", r1.c3 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 100::bigint
2067 EXPLAIN (VERBOSE, COSTS OFF)
2068 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;
2070 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2073 Relations: (public.ft1 t1) SEMI JOIN (public.ft2 t2)
2074 Remote SQL: SELECT r1."C 1" FROM "S 1"."T 1" r1 WHERE EXISTS (SELECT NULL FROM "S 1"."T 1" r2 WHERE ((r2."C 1" = r1."C 1"))) ORDER BY r1."C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 100::bigint
2077 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;
2092 -- ANTI JOIN, not pushed down
2093 EXPLAIN (VERBOSE, COSTS OFF)
2094 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;
2096 ---------------------------------------------------------------------------------------
2101 Merge Cond: (t1.c1 = t2.c2)
2102 -> Foreign Scan on public.ft1 t1
2104 Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
2105 -> Foreign Scan on public.ft2 t2
2107 Remote SQL: SELECT c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
2110 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;
2125 -- CROSS JOIN can be pushed down
2126 EXPLAIN (VERBOSE, COSTS OFF)
2127 SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
2129 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2131 Output: t1.c1, t2.c1
2132 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2133 Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (TRUE)) ORDER BY r1."C 1" ASC NULLS LAST, r2."C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 100::bigint
2136 SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
2151 -- different server, not pushed down. No result expected.
2152 EXPLAIN (VERBOSE, COSTS OFF)
2153 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;
2155 ---------------------------------------------------------------------------------------
2157 Output: t1.c1, t2.c1
2159 Output: t1.c1, t2.c1
2160 Merge Cond: (t2.c1 = t1.c1)
2161 -> Foreign Scan on public.ft6 t2
2162 Output: t2.c1, t2.c2, t2.c3
2163 Remote SQL: SELECT c1 FROM "S 1"."T 4" ORDER BY c1 ASC NULLS LAST
2165 Output: t1.c1, t1.c2, t1.c3
2166 -> Foreign Scan on public.ft5 t1
2167 Output: t1.c1, t1.c2, t1.c3
2168 Remote SQL: SELECT c1 FROM "S 1"."T 4" ORDER BY c1 ASC NULLS LAST
2171 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;
2176 -- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS
2177 -- JOIN since c8 in both tables has same value.
2178 EXPLAIN (VERBOSE, COSTS OFF)
2179 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;
2181 -------------------------------------------------------------------------
2183 Output: t1.c1, t2.c1
2185 Output: t1.c1, t2.c1
2186 Sort Key: t1.c1, t2.c1
2188 Output: t1.c1, t2.c1
2189 Merge Cond: (t1.c8 = t2.c8)
2191 Output: t1.c1, t1.c8
2193 -> Foreign Scan on public.ft1 t1
2194 Output: t1.c1, t1.c8
2195 Remote SQL: SELECT "C 1", c8 FROM "S 1"."T 1"
2197 Output: t2.c1, t2.c8
2199 -> Foreign Scan on public.ft2 t2
2200 Output: t2.c1, t2.c8
2201 Remote SQL: SELECT "C 1", c8 FROM "S 1"."T 1"
2204 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;
2219 -- unsafe conditions on one side (c8 has a UDT), not pushed down.
2220 EXPLAIN (VERBOSE, COSTS OFF)
2221 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;
2223 -----------------------------------------------------------------------------
2225 Output: t1.c1, t2.c1, t1.c3
2227 Output: t1.c1, t2.c1, t1.c3
2228 Sort Key: t1.c3, t1.c1
2230 Output: t1.c1, t2.c1, t1.c3
2231 Hash Cond: (t2.c1 = t1.c1)
2232 -> Foreign Scan on public.ft2 t2
2234 Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2236 Output: t1.c1, t1.c3
2237 -> Foreign Scan on public.ft1 t1
2238 Output: t1.c1, t1.c3
2239 Filter: (t1.c8 = 'foo'::user_enum)
2240 Remote SQL: SELECT "C 1", c3, c8 FROM "S 1"."T 1"
2243 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;
2258 -- join where unsafe to pushdown condition in WHERE clause has a column not
2259 -- in the SELECT clause. In this test unsafe clause needs to have column
2260 -- references from both joining sides so that the clause is not pushed down
2261 -- into one of the joining sides.
2262 EXPLAIN (VERBOSE, COSTS OFF)
2263 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;
2265 -------------------------------------------------------------------------------------------------------------------------------------------------------
2267 Output: t1.c1, t2.c1, t1.c3
2269 Output: t1.c1, t2.c1, t1.c3
2270 Sort Key: t1.c3, t1.c1
2272 Output: t1.c1, t2.c1, t1.c3
2273 Filter: (t1.c8 = t2.c8)
2274 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2275 Remote SQL: SELECT r1."C 1", r2."C 1", r1.c3, r1.c8, r2.c8 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1"))))
2278 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;
2293 -- Aggregate after UNION, for testing setrefs
2294 EXPLAIN (VERBOSE, COSTS OFF)
2295 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;
2297 ----------------------------------------------------------------------------------------------------------------------------------------------------
2299 Output: t1.c1, (avg((t1.c1 + t2.c1)))
2301 Output: t1.c1, (avg((t1.c1 + t2.c1)))
2304 Output: t1.c1, avg((t1.c1 + t2.c1))
2307 Output: t1.c1, t2.c1
2308 Group Key: t1.c1, t2.c1
2311 Output: t1.c1, t2.c1
2312 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2313 Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1"))))
2315 Output: t1_1.c1, t2_1.c1
2316 Relations: (public.ft1 t1_1) INNER JOIN (public.ft2 t2_1)
2317 Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1"))))
2320 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;
2322 ------+----------------------
2323 101 | 202.0000000000000000
2324 102 | 204.0000000000000000
2325 103 | 206.0000000000000000
2326 104 | 208.0000000000000000
2327 105 | 210.0000000000000000
2328 106 | 212.0000000000000000
2329 107 | 214.0000000000000000
2330 108 | 216.0000000000000000
2331 109 | 218.0000000000000000
2332 110 | 220.0000000000000000
2335 -- join with lateral reference
2336 EXPLAIN (VERBOSE, COSTS OFF)
2337 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;
2339 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2344 -> Index Scan using t1_pkey on "S 1"."T 1" t1
2345 Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
2349 -> Subquery Scan on q
2351 Output: t2.c1, t3.c1
2354 Output: t2.c1, t3.c1
2355 Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
2356 Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")) AND ((r1.c2 = $1::integer))))
2359 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;
2374 -- join with pseudoconstant quals
2375 EXPLAIN (VERBOSE, COSTS OFF)
2376 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1 AND CURRENT_USER = SESSION_USER) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
2378 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2380 Output: t1.c1, t2.c1, t1.c3
2382 Output: t1.c1, t2.c1, t1.c3
2383 One-Time Filter: (CURRENT_USER = SESSION_USER)
2385 Output: t1.c1, t1.c3, t2.c1
2386 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2387 Remote SQL: SELECT r1."C 1", r2."C 1", r1.c3 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST
2390 -- non-Var items in targetlist of the nullable rel of a join preventing
2391 -- push-down in some cases
2392 -- unable to push {ft1, ft2}
2393 EXPLAIN (VERBOSE, COSTS OFF)
2394 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;
2396 ---------------------------------------------------------------------------------------------------------------------------
2397 Nested Loop Left Join
2398 Output: (13), ft2.c1
2399 Join Filter: (13 = ft2.c1)
2400 -> Foreign Scan on public.ft2
2402 Remote SQL: SELECT "C 1" FROM "S 1"."T 1" WHERE (("C 1" >= 10)) AND (("C 1" <= 15)) ORDER BY "C 1" ASC NULLS LAST
2405 -> Foreign Scan on public.ft1
2407 Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE (("C 1" = 13))
2410 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;
2421 -- ok to push {ft1, ft2} but not {ft1, ft2, ft4}
2422 EXPLAIN (VERBOSE, COSTS OFF)
2423 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;
2425 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2426 Nested Loop Left Join
2427 Output: ft4.c1, (13), ft1.c1, ft2.c1
2428 Join Filter: (ft4.c1 = ft1.c1)
2429 -> Foreign Scan on public.ft4
2430 Output: ft4.c1, ft4.c2, ft4.c3
2431 Remote SQL: SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 10)) AND ((c1 <= 15))
2433 Output: ft1.c1, ft2.c1, (13)
2435 Output: ft1.c1, ft2.c1, 13
2436 Relations: (public.ft1) INNER JOIN (public.ft2)
2437 Remote SQL: SELECT r4."C 1", r5."C 1" FROM ("S 1"."T 1" r4 INNER JOIN "S 1"."T 1" r5 ON (((r5."C 1" = 12)) AND ((r4."C 1" = 12)))) ORDER BY r4."C 1" ASC NULLS LAST
2440 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;
2448 -- join with nullable side with some columns with null values
2449 UPDATE ft5 SET c3 = null where c1 % 9 = 0;
2450 EXPLAIN (VERBOSE, COSTS OFF)
2451 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;
2453 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2455 Output: ft5.*, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2
2456 Relations: (public.ft5) INNER JOIN (public.ft4)
2457 Remote SQL: SELECT CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1.c1, r1.c2, r1.c3) END, r1.c1, r1.c2, r1.c3, r2.c1, r2.c2 FROM ("S 1"."T 4" r1 INNER JOIN "S 1"."T 3" r2 ON (((r1.c1 = r2.c1)) AND ((r2.c1 >= 10)) AND ((r2.c1 <= 30)))) ORDER BY r1.c1 ASC NULLS LAST
2460 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;
2461 ft5 | c1 | c2 | c3 | c1 | c2
2462 ----------------+----+----+--------+----+----
2463 (12,13,AAA012) | 12 | 13 | AAA012 | 12 | 13
2464 (18,19,) | 18 | 19 | | 18 | 19
2465 (24,25,AAA024) | 24 | 25 | AAA024 | 24 | 25
2466 (30,31,AAA030) | 30 | 31 | AAA030 | 30 | 31
2469 -- multi-way join involving multiple merge joins
2470 -- (this case used to have EPQ-related planning problems)
2471 CREATE TABLE local_tbl (c1 int NOT NULL, c2 int NOT NULL, c3 text, CONSTRAINT local_tbl_pkey PRIMARY KEY (c1));
2472 INSERT INTO local_tbl SELECT id, id % 10, to_char(id, 'FM0000') FROM generate_series(1, 1000) id;
2474 SET enable_nestloop TO false;
2475 SET enable_hashjoin TO false;
2476 EXPLAIN (VERBOSE, COSTS OFF)
2477 SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1
2478 AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE;
2480 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2482 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
2484 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
2486 Merge Cond: (ft1.c2 = local_tbl.c1)
2488 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.*
2489 Relations: (((public.ft1) INNER JOIN (public.ft2)) INNER JOIN (public.ft4)) INNER JOIN (public.ft5)
2490 Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END, r3.c1, r3.c2, r3.c3, CASE WHEN (r3.*)::text IS NOT NULL THEN ROW(r3.c1, r3.c2, r3.c3) END, r4.c1, r4.c2, r4.c3, CASE WHEN (r4.*)::text IS NOT NULL THEN ROW(r4.c1, r4.c2, r4.c3) END FROM ((("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")) AND ((r2."C 1" < 100)) AND ((r1."C 1" < 100)))) INNER JOIN "S 1"."T 3" r3 ON (((r1.c2 = r3.c1)))) INNER JOIN "S 1"."T 4" r4 ON (((r1.c2 = r4.c1)))) ORDER BY r1.c2 ASC NULLS LAST FOR UPDATE OF r1 FOR UPDATE OF r2 FOR UPDATE OF r3 FOR UPDATE OF r4
2492 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.*
2493 Merge Cond: (ft1.c2 = ft5.c1)
2495 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.*
2496 Merge Cond: (ft1.c2 = ft4.c1)
2498 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.*
2501 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.*
2502 Merge Cond: (ft1.c1 = ft2.c1)
2504 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2506 -> Foreign Scan on public.ft1
2507 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2508 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 100)) FOR UPDATE
2510 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*
2511 -> Foreign Scan on public.ft2
2512 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*
2513 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 100)) ORDER BY "C 1" ASC NULLS LAST FOR UPDATE
2515 Output: ft4.c1, ft4.c2, ft4.c3, ft4.*
2517 -> Foreign Scan on public.ft4
2518 Output: ft4.c1, ft4.c2, ft4.c3, ft4.*
2519 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3" FOR UPDATE
2521 Output: ft5.c1, ft5.c2, ft5.c3, ft5.*
2523 -> Foreign Scan on public.ft5
2524 Output: ft5.c1, ft5.c2, ft5.c3, ft5.*
2525 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4" FOR UPDATE
2526 -> Index Scan using local_tbl_pkey on public.local_tbl
2527 Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid
2530 SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1
2531 AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE;
2532 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
2533 ----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------+----+----+--------+----+----+------
2534 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
2535 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
2536 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
2537 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
2538 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
2539 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
2540 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
2541 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
2542 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
2543 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
2546 RESET enable_nestloop;
2547 RESET enable_hashjoin;
2548 -- test that add_paths_with_pathkeys_for_rel() arranges for the epq_path to
2549 -- return columns needed by the parent ForeignScan node
2550 EXPLAIN (VERBOSE, COSTS OFF)
2551 SELECT * FROM local_tbl LEFT JOIN (SELECT ft1.*, COALESCE(ft1.c3 || ft2.c3, 'foobar') FROM ft1 INNER JOIN ft2 ON (ft1.c1 = ft2.c1 AND ft1.c1 < 100)) ss ON (local_tbl.c1 = ss.c1) ORDER BY local_tbl.c1 FOR UPDATE OF local_tbl;
2553 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2555 Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, (COALESCE((ft1.c3 || ft2.c3), 'foobar'::text)), local_tbl.ctid, ft1.*, ft2.*
2557 Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, (COALESCE((ft1.c3 || ft2.c3), 'foobar'::text)), local_tbl.ctid, ft1.*, ft2.*
2558 Merge Cond: (local_tbl.c1 = ft1.c1)
2559 -> Index Scan using local_tbl_pkey on public.local_tbl
2560 Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid
2562 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, (COALESCE((ft1.c3 || ft2.c3), 'foobar'::text))
2564 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, COALESCE((ft1.c3 || ft2.c3), 'foobar'::text)
2565 Relations: (public.ft1) INNER JOIN (public.ft2)
2566 Remote SQL: SELECT r4."C 1", r4.c2, r4.c3, r4.c4, r4.c5, r4.c6, r4.c7, r4.c8, CASE WHEN (r4.*)::text IS NOT NULL THEN ROW(r4."C 1", r4.c2, r4.c3, r4.c4, r4.c5, r4.c6, r4.c7, r4.c8) END, CASE WHEN (r5.*)::text IS NOT NULL THEN ROW(r5."C 1", r5.c2, r5.c3, r5.c4, r5.c5, r5.c6, r5.c7, r5.c8) END, r5.c3 FROM ("S 1"."T 1" r4 INNER JOIN "S 1"."T 1" r5 ON (((r5."C 1" = r4."C 1")) AND ((r4."C 1" < 100)))) ORDER BY r4."C 1" ASC NULLS LAST
2568 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, ft2.c3
2570 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, (COALESCE((ft1.c3 || ft2.c3), 'foobar'::text)), ft2.c3
2573 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, COALESCE((ft1.c3 || ft2.c3), 'foobar'::text), ft2.c3
2574 Hash Cond: (ft1.c1 = ft2.c1)
2575 -> Foreign Scan on public.ft1
2576 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2577 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 100))
2579 Output: ft2.*, ft2.c1, ft2.c3
2580 -> Foreign Scan on public.ft2
2581 Output: ft2.*, ft2.c1, ft2.c3
2582 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
2585 ALTER SERVER loopback OPTIONS (DROP extensions);
2586 ALTER SERVER loopback OPTIONS (ADD fdw_startup_cost '10000.0');
2587 EXPLAIN (VERBOSE, COSTS OFF)
2588 SELECT * FROM local_tbl LEFT JOIN (SELECT ft1.* FROM ft1 INNER JOIN ft2 ON (ft1.c1 = ft2.c1 AND ft1.c1 < 100 AND (ft1.c1 - postgres_fdw_abs(ft2.c2)) = 0)) ss ON (local_tbl.c3 = ss.c3) ORDER BY local_tbl.c1 FOR UPDATE OF local_tbl;
2590 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2592 Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, local_tbl.ctid, ft1.*, ft2.*
2593 -> Nested Loop Left Join
2594 Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, local_tbl.ctid, ft1.*, ft2.*
2595 Join Filter: (local_tbl.c3 = ft1.c3)
2596 -> Index Scan using local_tbl_pkey on public.local_tbl
2597 Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid
2599 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*
2601 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*
2602 Filter: ((ft1.c1 - postgres_fdw_abs(ft2.c2)) = 0)
2603 Relations: (public.ft1) INNER JOIN (public.ft2)
2604 Remote SQL: SELECT r4."C 1", r4.c2, r4.c3, r4.c4, r4.c5, r4.c6, r4.c7, r4.c8, CASE WHEN (r4.*)::text IS NOT NULL THEN ROW(r4."C 1", r4.c2, r4.c3, r4.c4, r4.c5, r4.c6, r4.c7, r4.c8) END, CASE WHEN (r5.*)::text IS NOT NULL THEN ROW(r5."C 1", r5.c2, r5.c3, r5.c4, r5.c5, r5.c6, r5.c7, r5.c8) END, r5.c2 FROM ("S 1"."T 1" r4 INNER JOIN "S 1"."T 1" r5 ON (((r5."C 1" = r4."C 1")) AND ((r4."C 1" < 100)))) ORDER BY r4.c3 ASC NULLS LAST
2606 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, ft2.c2
2609 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, ft2.c2
2610 Merge Cond: (ft1.c1 = ft2.c1)
2611 Join Filter: ((ft1.c1 - postgres_fdw_abs(ft2.c2)) = 0)
2613 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2615 -> Foreign Scan on public.ft1
2616 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2617 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 100))
2619 Output: ft2.*, ft2.c1, ft2.c2
2620 -> Foreign Scan on public.ft2
2621 Output: ft2.*, ft2.c1, ft2.c2
2622 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
2625 ALTER SERVER loopback OPTIONS (DROP fdw_startup_cost);
2626 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
2627 DROP TABLE local_tbl;
2628 -- check join pushdown in situations where multiple userids are involved
2629 CREATE ROLE regress_view_owner SUPERUSER;
2630 CREATE USER MAPPING FOR regress_view_owner SERVER loopback;
2631 GRANT SELECT ON ft4 TO regress_view_owner;
2632 GRANT SELECT ON ft5 TO regress_view_owner;
2633 CREATE VIEW v4 AS SELECT * FROM ft4;
2634 CREATE VIEW v5 AS SELECT * FROM ft5;
2635 ALTER VIEW v5 OWNER TO regress_view_owner;
2636 EXPLAIN (VERBOSE, COSTS OFF)
2637 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
2639 ----------------------------------------------------------------------
2641 Output: ft4.c1, ft5.c2, ft5.c1
2643 Output: ft4.c1, ft5.c2, ft5.c1
2644 Sort Key: ft4.c1, ft5.c1
2646 Output: ft4.c1, ft5.c2, ft5.c1
2647 Hash Cond: (ft4.c1 = ft5.c1)
2648 -> Foreign Scan on public.ft4
2649 Output: ft4.c1, ft4.c2, ft4.c3
2650 Remote SQL: SELECT c1 FROM "S 1"."T 3"
2652 Output: ft5.c2, ft5.c1
2653 -> Foreign Scan on public.ft5
2654 Output: ft5.c2, ft5.c1
2655 Remote SQL: SELECT c1, c2 FROM "S 1"."T 4"
2658 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;
2673 ALTER VIEW v4 OWNER TO regress_view_owner;
2674 EXPLAIN (VERBOSE, COSTS OFF)
2675 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
2677 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2679 Output: ft4.c1, ft5.c2, ft5.c1
2680 Relations: (public.ft4) LEFT JOIN (public.ft5)
2681 Remote SQL: SELECT r4.c1, r5.c2, r5.c1 FROM ("S 1"."T 3" r4 LEFT JOIN "S 1"."T 4" r5 ON (((r4.c1 = r5.c1)))) ORDER BY r4.c1 ASC NULLS LAST, r5.c1 ASC NULLS LAST LIMIT 10::bigint OFFSET 10::bigint
2684 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;
2699 EXPLAIN (VERBOSE, COSTS OFF)
2700 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
2702 ----------------------------------------------------------------------
2704 Output: ft4.c1, t2.c2, t2.c1
2706 Output: ft4.c1, t2.c2, t2.c1
2707 Sort Key: ft4.c1, t2.c1
2709 Output: ft4.c1, t2.c2, t2.c1
2710 Hash Cond: (ft4.c1 = t2.c1)
2711 -> Foreign Scan on public.ft4
2712 Output: ft4.c1, ft4.c2, ft4.c3
2713 Remote SQL: SELECT c1 FROM "S 1"."T 3"
2715 Output: t2.c2, t2.c1
2716 -> Foreign Scan on public.ft5 t2
2717 Output: t2.c2, t2.c1
2718 Remote SQL: SELECT c1, c2 FROM "S 1"."T 4"
2721 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;
2736 ALTER VIEW v4 OWNER TO CURRENT_USER;
2737 EXPLAIN (VERBOSE, COSTS OFF)
2738 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
2740 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2742 Output: ft4.c1, t2.c2, t2.c1
2743 Relations: (public.ft4) LEFT JOIN (public.ft5 t2)
2744 Remote SQL: SELECT r4.c1, r2.c2, r2.c1 FROM ("S 1"."T 3" r4 LEFT JOIN "S 1"."T 4" r2 ON (((r4.c1 = r2.c1)))) ORDER BY r4.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST LIMIT 10::bigint OFFSET 10::bigint
2747 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;
2762 ALTER VIEW v4 OWNER TO regress_view_owner;
2763 -- Make sure this big CROSS JOIN query is pushed down
2764 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 CROSS JOIN ft2 CROSS JOIN ft4 CROSS JOIN ft5;
2766 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
2769 Relations: Aggregate on ((((public.ft1) INNER JOIN (public.ft2)) INNER JOIN (public.ft4)) INNER JOIN (public.ft5))
2770 Remote SQL: SELECT count(*) FROM ((("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (TRUE)) INNER JOIN "S 1"."T 3" r4 ON (TRUE)) INNER JOIN "S 1"."T 4" r6 ON (TRUE))
2773 -- Make sure query cancellation works
2775 SET LOCAL statement_timeout = '10ms';
2776 select count(*) from ft1 CROSS JOIN ft2 CROSS JOIN ft4 CROSS JOIN ft5; -- this takes very long
2777 ERROR: canceling statement due to statement timeout
2779 -- ====================================================================
2780 -- Check that userid to use when querying the remote table is correctly
2781 -- propagated into foreign rels present in subqueries under an UNION ALL
2782 -- ====================================================================
2783 CREATE ROLE regress_view_owner_another;
2784 ALTER VIEW v4 OWNER TO regress_view_owner_another;
2785 GRANT SELECT ON ft4 TO regress_view_owner_another;
2786 ALTER FOREIGN TABLE ft4 OPTIONS (ADD use_remote_estimate 'true');
2787 -- The following should query the remote backing table of ft4 as user
2788 -- regress_view_owner_another, the view owner, though it fails as expected
2789 -- due to the lack of a user mapping for that user.
2790 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM v4;
2791 ERROR: user mapping not found for user "regress_view_owner_another", server "loopback"
2792 -- Likewise, but with the query under an UNION ALL
2793 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM (SELECT * FROM v4 UNION ALL SELECT * FROM v4);
2794 ERROR: user mapping not found for user "regress_view_owner_another", server "loopback"
2795 -- Should not get that error once a user mapping is created
2796 CREATE USER MAPPING FOR regress_view_owner_another SERVER loopback OPTIONS (password_required 'false');
2797 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM v4;
2799 --------------------------------------------------
2800 Foreign Scan on public.ft4
2801 Output: ft4.c1, ft4.c2, ft4.c3
2802 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
2805 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM (SELECT * FROM v4 UNION ALL SELECT * FROM v4);
2807 --------------------------------------------------------
2809 -> Foreign Scan on public.ft4
2810 Output: ft4.c1, ft4.c2, ft4.c3
2811 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
2812 -> Foreign Scan on public.ft4 ft4_1
2813 Output: ft4_1.c1, ft4_1.c2, ft4_1.c3
2814 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
2817 DROP USER MAPPING FOR regress_view_owner_another SERVER loopback;
2818 DROP OWNED BY regress_view_owner_another;
2819 DROP ROLE regress_view_owner_another;
2820 ALTER FOREIGN TABLE ft4 OPTIONS (SET use_remote_estimate 'false');
2822 DROP OWNED BY regress_view_owner;
2823 DROP ROLE regress_view_owner;
2824 -- ===================================================================
2825 -- Aggregate and grouping queries
2826 -- ===================================================================
2827 -- Simple aggregates
2828 explain (verbose, costs off)
2829 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;
2831 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2833 Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2
2834 Relations: Aggregate on (public.ft1)
2835 Remote SQL: SELECT count(c6), sum("C 1"), avg("C 1"), min(c2), max("C 1"), stddev(c2), c2 FROM "S 1"."T 1" WHERE ((c2 < 5)) GROUP BY 7 ORDER BY count(c6) ASC NULLS LAST, sum("C 1") ASC NULLS LAST
2838 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;
2839 count | sum | avg | min | max | stddev | sum2
2840 -------+-------+----------------------+-----+------+--------+-------
2841 100 | 49600 | 496.0000000000000000 | 1 | 991 | 0 | 49600
2842 100 | 49700 | 497.0000000000000000 | 2 | 992 | 0 | 49700
2843 100 | 49800 | 498.0000000000000000 | 3 | 993 | 0 | 49800
2844 100 | 49900 | 499.0000000000000000 | 4 | 994 | 0 | 49900
2845 100 | 50500 | 505.0000000000000000 | 0 | 1000 | 0 | 50500
2848 explain (verbose, costs off)
2849 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;
2851 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2853 Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2
2854 Relations: Aggregate on (public.ft1)
2855 Remote SQL: SELECT count(c6), sum("C 1"), avg("C 1"), min(c2), max("C 1"), stddev(c2), c2 FROM "S 1"."T 1" WHERE ((c2 < 5)) GROUP BY 7 ORDER BY count(c6) ASC NULLS LAST, sum("C 1") ASC NULLS LAST LIMIT 1::bigint
2858 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;
2859 count | sum | avg | min | max | stddev | sum2
2860 -------+-------+----------------------+-----+-----+--------+-------
2861 100 | 49600 | 496.0000000000000000 | 1 | 991 | 0 | 49600
2864 -- Aggregate is not pushed down as aggregation contains random()
2865 explain (verbose, costs off)
2866 select sum(c1 * (random() <= 1)::int) as sum, avg(c1) from ft1;
2868 -------------------------------------------------------------------------------
2870 Output: sum((c1 * ((random() <= '1'::double precision))::integer)), avg(c1)
2871 -> Foreign Scan on public.ft1
2873 Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2876 -- Aggregate over join query
2877 explain (verbose, costs off)
2878 select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6;
2880 --------------------------------------------------------------------------------------------------------------------------------------------------
2882 Output: (count(*)), (sum(t1.c1)), (avg(t2.c1))
2883 Relations: Aggregate on ((public.ft1 t1) INNER JOIN (public.ft1 t2))
2884 Remote SQL: SELECT count(*), sum(r1."C 1"), avg(r2."C 1") FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2.c2 = 6)) AND ((r1.c2 = 6))))
2887 select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6;
2889 -------+---------+----------------------
2890 10000 | 5010000 | 501.0000000000000000
2893 -- Not pushed down due to local conditions present in underneath input rel
2894 explain (verbose, costs off)
2895 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;
2897 ----------------------------------------------------------------------------------------------------------------------------
2899 Output: sum(t1.c1), count(t2.c1)
2901 Output: t1.c1, t2.c1
2902 Filter: (((((t1.c1 * t2.c1) / (t1.c1 * t2.c1)))::double precision * random()) <= '1'::double precision)
2903 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2904 Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1"))))
2907 -- GROUP BY clause having expressions
2908 explain (verbose, costs off)
2909 select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
2911 ------------------------------------------------------------------------------------------------------------------
2913 Output: ((c2 / 2)), ((sum(c2) * (c2 / 2)))
2914 Relations: Aggregate on (public.ft1)
2915 Remote SQL: SELECT (c2 / 2), (sum(c2) * (c2 / 2)) FROM "S 1"."T 1" GROUP BY 1 ORDER BY (c2 / 2) ASC NULLS LAST
2918 select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
2920 ----------+----------
2928 -- Aggregates in subquery are pushed down.
2929 set enable_incremental_sort = off;
2930 explain (verbose, costs off)
2931 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;
2933 ---------------------------------------------------------------------------------------------------------------------------------------------
2935 Output: count(ft1.c2), sum(ft1.c2)
2937 Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision))
2938 Relations: Aggregate on (public.ft1)
2939 Remote SQL: SELECT c2, sum("C 1"), sqrt("C 1") FROM "S 1"."T 1" GROUP BY 1, 3 ORDER BY c2 ASC NULLS LAST, sum("C 1") ASC NULLS LAST
2942 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;
2948 reset enable_incremental_sort;
2949 -- Aggregate is still pushed down by taking unshippable expression out
2950 explain (verbose, costs off)
2951 select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2;
2953 ---------------------------------------------------------------------------------------------------
2955 Output: ((c2 * ((random() <= '1'::double precision))::integer)), ((sum(c1) * c2)), c2
2956 Sort Key: ((ft1.c2 * ((random() <= '1'::double precision))::integer)), ((sum(ft1.c1) * ft1.c2))
2958 Output: (c2 * ((random() <= '1'::double precision))::integer), ((sum(c1) * c2)), c2
2959 Relations: Aggregate on (public.ft1)
2960 Remote SQL: SELECT (sum("C 1") * c2), c2 FROM "S 1"."T 1" GROUP BY 2
2963 select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2;
2978 -- Aggregate with unshippable GROUP BY clause are not pushed
2979 explain (verbose, costs off)
2980 select c2 * (random() <= 1)::int as c2 from ft2 group by c2 * (random() <= 1)::int order by 1;
2982 ------------------------------------------------------------------------------
2984 Output: ((c2 * ((random() <= '1'::double precision))::integer))
2985 Sort Key: ((ft2.c2 * ((random() <= '1'::double precision))::integer))
2987 Output: ((c2 * ((random() <= '1'::double precision))::integer))
2988 Group Key: (ft2.c2 * ((random() <= '1'::double precision))::integer)
2989 -> Foreign Scan on public.ft2
2990 Output: (c2 * ((random() <= '1'::double precision))::integer)
2991 Remote SQL: SELECT c2 FROM "S 1"."T 1"
2994 -- GROUP BY clause in various forms, cardinal, alias and constant expression
2995 explain (verbose, costs off)
2996 select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2;
2998 ------------------------------------------------------------------------------------------------------------
3000 Output: (count(c2)), c2, 5, 7.0, 9
3001 Relations: Aggregate on (public.ft1)
3002 Remote SQL: SELECT count(c2), c2, 5, 7.0, 9 FROM "S 1"."T 1" GROUP BY 2, 3, 5 ORDER BY c2 ASC NULLS LAST
3005 select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2;
3020 -- GROUP BY clause referring to same column multiple times
3021 -- Also, ORDER BY contains an aggregate function
3022 explain (verbose, costs off)
3023 select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1);
3025 ----------------------------------------------------------------------------------------------------------------------------
3027 Output: c2, c2, (sum(c1))
3028 Relations: Aggregate on (public.ft1)
3029 Remote SQL: SELECT c2, c2, sum("C 1") FROM "S 1"."T 1" WHERE ((c2 > 6)) GROUP BY 1, 2 ORDER BY sum("C 1") ASC NULLS LAST
3032 select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1);
3040 -- Testing HAVING clause shippability
3041 explain (verbose, costs off)
3042 select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
3044 ------------------------------------------------------------------------------------------------------------------------------------------------------------
3046 Output: c2, (sum(c1))
3047 Relations: Aggregate on (public.ft2)
3048 Remote SQL: SELECT c2, sum("C 1") FROM "S 1"."T 1" GROUP BY 1 HAVING ((avg("C 1") < 500::numeric)) AND ((sum("C 1") < 49800)) ORDER BY c2 ASC NULLS LAST
3051 select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
3058 -- Unshippable HAVING clause will be evaluated locally, and other qual in HAVING clause is pushed down
3059 explain (verbose, costs off)
3060 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;
3062 ---------------------------------------------------------------------------------------------------------------------------------------
3066 Output: ft1.c5, NULL::bigint, (sqrt((ft1.c2)::double precision))
3067 Filter: (((((avg(ft1.c1)) / (avg(ft1.c1))))::double precision * random()) <= '1'::double precision)
3068 Relations: Aggregate on (public.ft1)
3069 Remote SQL: SELECT c5, NULL::bigint, sqrt(c2), avg("C 1") FROM "S 1"."T 1" GROUP BY 1, 3 HAVING ((avg("C 1") < 500::numeric))
3072 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;
3078 -- Aggregate in HAVING clause is not pushable, and thus aggregation is not pushed down
3079 explain (verbose, costs off)
3080 select sum(c1) from ft1 group by c2 having avg(c1 * (random() <= 1)::int) > 100 order by 1;
3082 ---------------------------------------------------------------------------------------------------
3084 Output: (sum(c1)), c2
3085 Sort Key: (sum(ft1.c1))
3089 Filter: (avg((ft1.c1 * ((random() <= '1'::double precision))::integer)) > '100'::numeric)
3090 -> Foreign Scan on public.ft1
3092 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1"
3095 -- Remote aggregate in combination with a local Param (for the output
3096 -- of an initplan) can be trouble, per bug #15781
3097 explain (verbose, costs off)
3098 select exists(select 1 from pg_enum), sum(c1) from ft1;
3100 --------------------------------------------------
3102 Output: (InitPlan 1).col1, (sum(ft1.c1))
3103 Relations: Aggregate on (public.ft1)
3104 Remote SQL: SELECT sum("C 1") FROM "S 1"."T 1"
3106 -> Seq Scan on pg_catalog.pg_enum
3109 select exists(select 1 from pg_enum), sum(c1) from ft1;
3115 explain (verbose, costs off)
3116 select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1;
3118 ---------------------------------------------------
3120 Output: (InitPlan 1).col1, sum(ft1.c1)
3122 -> Seq Scan on pg_catalog.pg_enum
3123 -> Foreign Scan on public.ft1
3125 Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
3128 select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1;
3134 -- Testing ORDER BY, DISTINCT, FILTER, Ordered-sets and VARIADIC within aggregates
3135 -- ORDER BY within aggregate, same column used to order
3136 explain (verbose, costs off)
3137 select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1;
3139 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3141 Output: (array_agg(c1 ORDER BY c1)), c2
3142 Relations: Aggregate on (public.ft1)
3143 Remote SQL: SELECT array_agg("C 1" ORDER BY "C 1" ASC NULLS LAST), c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) GROUP BY 2 ORDER BY array_agg("C 1" ORDER BY "C 1" ASC NULLS LAST) ASC NULLS LAST
3146 select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1;
3148 --------------------------------
3149 {1,11,21,31,41,51,61,71,81,91}
3150 {2,12,22,32,42,52,62,72,82,92}
3151 {3,13,23,33,43,53,63,73,83,93}
3152 {4,14,24,34,44,54,64,74,84,94}
3153 {5,15,25,35,45,55,65,75,85,95}
3154 {6,16,26,36,46,56,66,76,86,96}
3155 {7,17,27,37,47,57,67,77,87,97}
3156 {8,18,28,38,48,58,68,78,88,98}
3157 {9,19,29,39,49,59,69,79,89,99}
3158 {10,20,30,40,50,60,70,80,90}
3161 -- ORDER BY within aggregate, different column used to order also using DESC
3162 explain (verbose, costs off)
3163 select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50;
3165 -------------------------------------------------------------------------------------------------------------------------
3167 Output: (array_agg(c5 ORDER BY c1 DESC))
3168 Relations: Aggregate on (public.ft2)
3169 Remote SQL: SELECT array_agg(c5 ORDER BY "C 1" DESC NULLS FIRST) FROM "S 1"."T 1" WHERE (("C 1" < 50)) AND ((c2 = 6))
3172 select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50;
3174 ------------------------------------------------------------------------------------------------------------------------------------------
3175 {"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"}
3178 -- DISTINCT within aggregate
3179 explain (verbose, costs off)
3180 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;
3182 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3184 Output: (array_agg(DISTINCT (t1.c1 % 5))), ((t2.c1 % 3))
3185 Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
3186 Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5)), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2 ORDER BY array_agg(DISTINCT (r1.c1 % 5)) ASC NULLS LAST
3189 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;
3196 -- DISTINCT combined with ORDER BY within aggregate
3197 explain (verbose, costs off)
3198 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;
3200 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3202 Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))), ((t2.c1 % 3))
3203 Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
3204 Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) ASC NULLS LAST), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2 ORDER BY array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) ASC NULLS LAST) ASC NULLS LAST
3207 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;
3214 explain (verbose, costs off)
3215 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;
3217 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3219 Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)), ((t2.c1 % 3))
3220 Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
3221 Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) DESC NULLS LAST), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2 ORDER BY array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) DESC NULLS LAST) ASC NULLS LAST
3224 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;
3231 -- FILTER within aggregate
3232 explain (verbose, costs off)
3233 select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last;
3235 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3237 Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2
3238 Relations: Aggregate on (public.ft1)
3239 Remote SQL: SELECT sum("C 1") FILTER (WHERE (("C 1" < 100) AND (c2 > 5))), c2 FROM "S 1"."T 1" GROUP BY 2 ORDER BY sum("C 1") FILTER (WHERE (("C 1" < 100) AND (c2 > 5))) ASC NULLS LAST
3242 select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last;
3257 -- DISTINCT, ORDER BY and FILTER within aggregate
3258 explain (verbose, costs off)
3259 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;
3261 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3263 Output: (sum((c1 % 3))), (sum(DISTINCT (c1 % 3) ORDER BY (c1 % 3)) FILTER (WHERE ((c1 % 3) < 2))), c2
3264 Relations: Aggregate on (public.ft1)
3265 Remote SQL: SELECT sum(("C 1" % 3)), sum(DISTINCT ("C 1" % 3) ORDER BY (("C 1" % 3)) ASC NULLS LAST) FILTER (WHERE (("C 1" % 3) < 2)), c2 FROM "S 1"."T 1" WHERE ((c2 = 6)) GROUP BY 3
3268 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;
3274 -- Outer query is aggregation query
3275 explain (verbose, costs off)
3276 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;
3278 ------------------------------------------------------------------------------------------------------------------------------
3280 Output: ((SubPlan 1))
3282 Output: ((SubPlan 1))
3283 Sort Key: ((SubPlan 1))
3286 Relations: Aggregate on (public.ft2 t2)
3287 Remote SQL: SELECT count(*) FILTER (WHERE ((c2 = 6) AND ("C 1" < 10))) FROM "S 1"."T 1" WHERE (((c2 % 6) = 0))
3289 -> Foreign Scan on public.ft1 t1
3290 Output: (count(*) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))))
3291 Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE (("C 1" = 6))
3294 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;
3300 -- Inner query is aggregation query
3301 explain (verbose, costs off)
3302 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;
3304 ------------------------------------------------------------------------------------------------------------------------------------------------------
3306 Output: ((SubPlan 1))
3308 Output: ((SubPlan 1))
3309 Sort Key: ((SubPlan 1))
3310 -> Foreign Scan on public.ft2 t2
3312 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (((c2 % 6) = 0))
3315 Output: (count(t1.c1) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))))
3316 Relations: Aggregate on (public.ft1 t1)
3317 Remote SQL: SELECT count("C 1") FILTER (WHERE (($1::integer = 6) AND ($2::integer < 10))) FROM "S 1"."T 1" WHERE (("C 1" = 6))
3320 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;
3327 -- Aggregate not pushed down as FILTER condition is not pushable
3328 explain (verbose, costs off)
3329 select sum(c1) filter (where (c1 / c1) * random() <= 1) from ft1 group by c2 order by 1;
3331 ------------------------------------------------------------------------------------------------------------------------
3333 Output: (sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision))), c2
3334 Sort Key: (sum(ft1.c1) FILTER (WHERE ((((ft1.c1 / ft1.c1))::double precision * random()) <= '1'::double precision)))
3336 Output: sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision)), c2
3338 -> Foreign Scan on public.ft1
3340 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1"
3343 explain (verbose, costs off)
3344 select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1;
3346 -------------------------------------------------------------------------------
3348 Output: sum(ft1.c2) FILTER (WHERE (ANY (ft1.c2 = (hashed SubPlan 1).col1)))
3349 -> Foreign Scan on public.ft1
3351 Remote SQL: SELECT c2 FROM "S 1"."T 1"
3353 -> Foreign Scan on public.ft1 ft1_1
3355 Remote SQL: SELECT c2 FROM "S 1"."T 1" WHERE ((c2 < 5))
3358 -- Ordered-sets within aggregate
3359 explain (verbose, costs off)
3360 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;
3362 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3364 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)))
3367 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)))
3368 Relations: Aggregate on (public.ft1)
3369 Remote SQL: SELECT c2, rank('10'::character varying) WITHIN GROUP (ORDER BY c6 ASC NULLS LAST), percentile_cont((c2 / 10::numeric)) WITHIN GROUP (ORDER BY ("C 1") ASC NULLS LAST) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1 HAVING ((percentile_cont((c2 / 10::numeric)) WITHIN GROUP (ORDER BY ("C 1") ASC NULLS LAST) < 500::double precision))
3372 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;
3373 c2 | rank | percentile_cont
3374 ----+------+-----------------
3382 -- Using multiple arguments within aggregates
3383 explain (verbose, costs off)
3384 select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1;
3386 --------------------------------------------------------------------------------------------------------------------------------------------------------------------
3388 Output: c1, (rank(c1, c2) WITHIN GROUP (ORDER BY c1, c2)), c2
3389 Relations: Aggregate on (public.ft1)
3390 Remote SQL: SELECT "C 1", rank("C 1", c2) WITHIN GROUP (ORDER BY "C 1" ASC NULLS LAST, c2 ASC NULLS LAST), c2 FROM "S 1"."T 1" WHERE (("C 1" = 6)) GROUP BY 1, 3
3393 select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1;
3399 -- User defined function for user defined aggregate, VARIADIC
3400 create function least_accum(anyelement, variadic anyarray)
3401 returns anyelement language sql as
3402 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)';
3403 create aggregate least_agg(variadic items anyarray) (
3404 stype = anyelement, sfunc = least_accum
3406 -- Disable hash aggregation for plan stability.
3407 set enable_hashagg to false;
3408 -- Not pushed down due to user defined aggregate
3409 explain (verbose, costs off)
3410 select c2, least_agg(c1) from ft1 group by c2 order by c2;
3412 ----------------------------------------------------------------------------------
3414 Output: c2, least_agg(VARIADIC ARRAY[c1])
3416 -> Foreign Scan on public.ft1
3418 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
3421 -- Add function and aggregate into extension
3422 alter extension postgres_fdw add function least_accum(anyelement, variadic anyarray);
3423 alter extension postgres_fdw add aggregate least_agg(variadic items anyarray);
3424 alter server loopback options (set extensions 'postgres_fdw');
3425 -- Now aggregate will be pushed. Aggregate will display VARIADIC argument.
3426 explain (verbose, costs off)
3427 select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2;
3429 -----------------------------------------------------------------------------------------------------------------------
3431 Output: c2, (least_agg(VARIADIC ARRAY[c1]))
3434 Output: c2, (least_agg(VARIADIC ARRAY[c1]))
3435 Relations: Aggregate on (public.ft1)
3436 Remote SQL: SELECT c2, public.least_agg(VARIADIC ARRAY["C 1"]) FROM "S 1"."T 1" WHERE ((c2 < 100)) GROUP BY 1
3439 select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2;
3454 -- Remove function and aggregate from extension
3455 alter extension postgres_fdw drop function least_accum(anyelement, variadic anyarray);
3456 alter extension postgres_fdw drop aggregate least_agg(variadic items anyarray);
3457 alter server loopback options (set extensions 'postgres_fdw');
3458 -- Not pushed down as we have dropped objects from extension.
3459 explain (verbose, costs off)
3460 select c2, least_agg(c1) from ft1 group by c2 order by c2;
3462 ----------------------------------------------------------------------------------
3464 Output: c2, least_agg(VARIADIC ARRAY[c1])
3466 -> Foreign Scan on public.ft1
3468 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
3472 reset enable_hashagg;
3473 drop aggregate least_agg(variadic items anyarray);
3474 drop function least_accum(anyelement, variadic anyarray);
3475 -- Testing USING OPERATOR() in ORDER BY within aggregate.
3476 -- For this, we need user defined operators along with operator family and
3477 -- operator class. Create those and then add them in extension. Note that
3478 -- user defined objects are considered unshippable unless they are part of
3480 create operator public.<^ (
3485 create operator public.=^ (
3490 create operator public.>^ (
3495 create operator family my_op_family using btree;
3496 create function my_op_cmp(a int, b int) returns int as
3497 $$begin return btint4cmp(a, b); end $$ language plpgsql;
3498 create operator class my_op_class for type int using btree family my_op_family as
3499 operator 1 public.<^,
3500 operator 3 public.=^,
3501 operator 5 public.>^,
3502 function 1 my_op_cmp(int, int);
3503 -- This will not be pushed as user defined sort operator is not part of the
3505 explain (verbose, costs off)
3506 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3508 --------------------------------------------------------------------------------------------------
3510 Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2
3513 Sort Key: ft2.c1 USING <^
3514 -> Foreign Scan on public.ft2
3516 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6))
3519 -- This should not be pushed either.
3520 explain (verbose, costs off)
3521 select * from ft2 order by c1 using operator(public.<^);
3523 -------------------------------------------------------------------------------
3525 Output: c1, c2, c3, c4, c5, c6, c7, c8
3526 Sort Key: ft2.c1 USING <^
3527 -> Foreign Scan on public.ft2
3528 Output: c1, c2, c3, c4, c5, c6, c7, c8
3529 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
3532 -- Update local stats on ft2
3534 -- Add into extension
3535 alter extension postgres_fdw add operator class my_op_class using btree;
3536 alter extension postgres_fdw add function my_op_cmp(a int, b int);
3537 alter extension postgres_fdw add operator family my_op_family using btree;
3538 alter extension postgres_fdw add operator public.<^(int, int);
3539 alter extension postgres_fdw add operator public.=^(int, int);
3540 alter extension postgres_fdw add operator public.>^(int, int);
3541 alter server loopback options (set extensions 'postgres_fdw');
3542 -- Now this will be pushed as sort operator is part of the extension.
3543 alter server loopback options (add fdw_tuple_cost '0.5');
3544 explain (verbose, costs off)
3545 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3547 ----------------------------------------------------------------------------------------------------------------------------------------------------------------
3549 Output: (array_agg(c1 ORDER BY c1 USING <^ NULLS LAST)), c2
3550 Relations: Aggregate on (public.ft2)
3551 Remote SQL: SELECT array_agg("C 1" ORDER BY "C 1" USING OPERATOR(public.<^) NULLS LAST), c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6)) GROUP BY 2
3554 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3556 --------------------------------
3557 {6,16,26,36,46,56,66,76,86,96}
3560 alter server loopback options (drop fdw_tuple_cost);
3561 -- This should be pushed too.
3562 explain (verbose, costs off)
3563 select * from ft2 order by c1 using operator(public.<^);
3565 -----------------------------------------------------------------------------------------------------------------------------
3566 Foreign Scan on public.ft2
3567 Output: c1, c2, c3, c4, c5, c6, c7, c8
3568 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" ORDER BY "C 1" USING OPERATOR(public.<^) NULLS LAST
3571 -- Remove from extension
3572 alter extension postgres_fdw drop operator class my_op_class using btree;
3573 alter extension postgres_fdw drop function my_op_cmp(a int, b int);
3574 alter extension postgres_fdw drop operator family my_op_family using btree;
3575 alter extension postgres_fdw drop operator public.<^(int, int);
3576 alter extension postgres_fdw drop operator public.=^(int, int);
3577 alter extension postgres_fdw drop operator public.>^(int, int);
3578 alter server loopback options (set extensions 'postgres_fdw');
3579 -- This will not be pushed as sort operator is now removed from the extension.
3580 explain (verbose, costs off)
3581 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3583 --------------------------------------------------------------------------------------------------
3585 Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2
3588 Sort Key: ft2.c1 USING <^
3589 -> Foreign Scan on public.ft2
3591 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6))
3595 drop operator class my_op_class using btree;
3596 drop function my_op_cmp(a int, b int);
3597 drop operator family my_op_family using btree;
3598 drop operator public.>^(int, int);
3599 drop operator public.=^(int, int);
3600 drop operator public.<^(int, int);
3601 -- Input relation to aggregate push down hook is not safe to pushdown and thus
3602 -- the aggregate cannot be pushed down to foreign server.
3603 explain (verbose, costs off)
3604 select count(t1.c3) from ft2 t1 left join ft2 t2 on (t1.c1 = random() * t2.c2);
3606 -------------------------------------------------------------------------------------------
3608 Output: count(t1.c3)
3609 -> Nested Loop Left Join
3611 Join Filter: ((t1.c1)::double precision = (random() * (t2.c2)::double precision))
3612 -> Foreign Scan on public.ft2 t1
3613 Output: t1.c3, t1.c1
3614 Remote SQL: SELECT "C 1", c3 FROM "S 1"."T 1"
3617 -> Foreign Scan on public.ft2 t2
3619 Remote SQL: SELECT c2 FROM "S 1"."T 1"
3622 -- Subquery in FROM clause having aggregate
3623 explain (verbose, costs off)
3624 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;
3626 -----------------------------------------------------------------------------------------------
3628 Output: (count(*)), x.b
3629 Sort Key: (count(*)), x.b
3631 Output: count(*), x.b
3636 Hash Cond: (ft1.c2 = x.a)
3637 -> Foreign Scan on public.ft1
3639 Remote SQL: SELECT c2 FROM "S 1"."T 1"
3642 -> Subquery Scan on x
3645 Output: ft1_1.c2, (sum(ft1_1.c1))
3646 Relations: Aggregate on (public.ft1 ft1_1)
3647 Remote SQL: SELECT c2, sum("C 1") FROM "S 1"."T 1" GROUP BY 1
3650 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;
3665 -- FULL join with IS NULL check in HAVING
3666 explain (verbose, costs off)
3667 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;
3669 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3671 Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1
3672 Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
3673 Remote SQL: SELECT avg(r1.c1), sum(r2.c1), r2.c1 FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) GROUP BY 3 HAVING ((((avg(r1.c1) IS NULL) AND (sum(r2.c1) < 10)) OR (sum(r2.c1) IS NULL))) ORDER BY avg(r1.c1) ASC NULLS LAST, sum(r2.c1) ASC NULLS LAST
3676 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;
3678 ---------------------+-----
3679 51.0000000000000000 |
3684 -- Aggregate over FULL join needing to deparse the joining relations as
3686 explain (verbose, costs off)
3687 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);
3689 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3691 Output: (count(*)), (sum(ft4.c1)), (avg(ft5.c1))
3692 Relations: Aggregate on ((public.ft4) FULL JOIN (public.ft5))
3693 Remote SQL: SELECT count(*), sum(s4.c1), avg(s5.c1) FROM ((SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s4(c1) FULL JOIN (SELECT c1 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s5(c1) ON (((s4.c1 = s5.c1))))
3696 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);
3698 -------+-----+---------------------
3699 8 | 330 | 55.5000000000000000
3702 -- ORDER BY expression is part of the target list but not pushed down to
3704 explain (verbose, costs off)
3705 select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1;
3707 --------------------------------------------------------------------------------
3709 Output: (((sum(c2)) * ((random() <= '1'::double precision))::integer))
3710 Sort Key: (((sum(ft1.c2)) * ((random() <= '1'::double precision))::integer))
3712 Output: ((sum(c2)) * ((random() <= '1'::double precision))::integer)
3713 Relations: Aggregate on (public.ft1)
3714 Remote SQL: SELECT sum(c2) FROM "S 1"."T 1"
3717 select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1;
3723 -- LATERAL join, with parameterization
3724 set enable_hashagg to false;
3725 explain (verbose, costs off)
3726 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;
3728 ------------------------------------------------------------------------------------------------------
3730 Output: t1.c2, qry.sum
3733 Output: t1.c2, qry.sum
3734 -> Index Scan using t1_pkey on "S 1"."T 1" t1
3735 Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
3736 Index Cond: (t1."C 1" < 100)
3738 -> Subquery Scan on qry
3739 Output: qry.sum, t2.c1
3740 Filter: ((t1.c2 * 2) = qry.sum)
3742 Output: (sum((t2.c1 + t1."C 1"))), t2.c1
3743 Relations: Aggregate on (public.ft2 t2)
3744 Remote SQL: SELECT sum(("C 1" + $1::integer)), "C 1" FROM "S 1"."T 1" GROUP BY 2
3747 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;
3754 reset enable_hashagg;
3755 -- bug #15613: bad plan for foreign table scan with lateral reference
3756 EXPLAIN (VERBOSE, COSTS OFF)
3757 SELECT ref_0.c2, subq_1.*
3759 "S 1"."T 1" AS ref_0,
3761 SELECT ref_0."C 1" c1, subq_0.*
3762 FROM (SELECT ref_0.c2, ref_1.c3
3763 FROM ft1 AS ref_1) AS subq_0
3764 RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3)
3766 WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001'
3767 ORDER BY ref_0."C 1";
3769 ---------------------------------------------------------------------------------------------------------
3771 Output: ref_0.c2, ref_0."C 1", (ref_0.c2), ref_1.c3, ref_0."C 1"
3773 Output: ref_0.c2, ref_0."C 1", ref_1.c3, (ref_0.c2)
3774 -> Index Scan using t1_pkey on "S 1"."T 1" ref_0
3775 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
3776 Index Cond: (ref_0."C 1" < 10)
3777 -> Foreign Scan on public.ft1 ref_1
3778 Output: ref_1.c3, ref_0.c2
3779 Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE ((c3 = '00001'))
3782 -> Foreign Scan on public.ft2 ref_3
3784 Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE ((c3 = '00001'))
3787 SELECT ref_0.c2, subq_1.*
3789 "S 1"."T 1" AS ref_0,
3791 SELECT ref_0."C 1" c1, subq_0.*
3792 FROM (SELECT ref_0.c2, ref_1.c3
3793 FROM ft1 AS ref_1) AS subq_0
3794 RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3)
3796 WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001'
3797 ORDER BY ref_0."C 1";
3799 ----+----+----+-------
3811 -- Check with placeHolderVars
3812 explain (verbose, costs off)
3813 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);
3815 ----------------------------------------------------------------------------------------------------------------------------------------------------------
3817 Output: sum(q.a), count(q.b)
3818 -> Nested Loop Left Join
3821 Join Filter: ((ft4.c1)::numeric <= q.b)
3822 -> Foreign Scan on public.ft4
3823 Output: ft4.c1, ft4.c2, ft4.c3
3824 Remote SQL: SELECT c1 FROM "S 1"."T 3"
3827 -> Subquery Scan on q
3830 Output: 13, (avg(ft1.c1)), NULL::bigint
3831 Relations: Aggregate on ((public.ft2) LEFT JOIN (public.ft1))
3832 Remote SQL: SELECT 13, avg(r1."C 1"), NULL::bigint FROM ("S 1"."T 1" r2 LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1"))))
3835 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);
3841 -- Not supported cases
3843 explain (verbose, costs off)
3844 select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last;
3846 ------------------------------------------------------------------------------
3848 Output: c2, (sum(c1))
3854 -> Foreign Scan on public.ft1
3856 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3))
3859 select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last;
3868 explain (verbose, costs off)
3869 select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last;
3871 ------------------------------------------------------------------------------
3873 Output: c2, (sum(c1))
3879 -> Foreign Scan on public.ft1
3881 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3))
3884 select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last;
3893 explain (verbose, costs off)
3894 select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last;
3896 ----------------------------------------------------------------------------------
3898 Output: c2, c6, (sum(c1))
3899 Sort Key: ft1.c2, ft1.c6
3901 Output: c2, c6, sum(c1)
3904 -> Foreign Scan on public.ft1
3906 Remote SQL: SELECT "C 1", c2, c6 FROM "S 1"."T 1" WHERE ((c2 < 3))
3909 select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last;
3920 explain (verbose, costs off)
3921 select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last;
3923 ------------------------------------------------------------------------------
3925 Output: c2, (sum(c1)), (GROUPING(c2))
3928 Output: c2, sum(c1), GROUPING(c2)
3930 -> Foreign Scan on public.ft1
3932 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3))
3935 select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last;
3937 ----+-------+----------
3943 -- DISTINCT itself is not pushed down, whereas underneath aggregate is pushed
3944 explain (verbose, costs off)
3945 select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1;
3947 -------------------------------------------------------------------------------------------------------
3949 Output: ((sum(c1) / 1000)), c2
3951 Output: ((sum(c1) / 1000)), c2
3952 Sort Key: ((sum(ft2.c1) / 1000))
3954 Output: ((sum(c1) / 1000)), c2
3955 Relations: Aggregate on (public.ft2)
3956 Remote SQL: SELECT (sum("C 1") / 1000), c2 FROM "S 1"."T 1" WHERE ((c2 < 6)) GROUP BY 2
3959 select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1;
3967 explain (verbose, costs off)
3968 select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1;
3970 ------------------------------------------------------------------------------------------------------------
3972 Output: c2, (sum(c2)), (count(c2) OVER (?)), ((c2 % 2))
3975 Output: c2, (sum(c2)), count(c2) OVER (?), ((c2 % 2))
3977 Output: c2, ((c2 % 2)), (sum(c2))
3978 Sort Key: ((ft2.c2 % 2))
3980 Output: c2, ((c2 % 2)), (sum(c2))
3981 Relations: Aggregate on (public.ft2)
3982 Remote SQL: SELECT c2, (c2 % 2), sum(c2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1
3985 select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1;
4000 explain (verbose, costs off)
4001 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;
4003 ---------------------------------------------------------------------------------------------------
4005 Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2))
4008 Output: c2, array_agg(c2) OVER (?), ((c2 % 2))
4010 Output: c2, ((c2 % 2))
4011 Sort Key: ((ft1.c2 % 2)), ft1.c2 DESC
4013 Output: c2, ((c2 % 2))
4014 Relations: Aggregate on (public.ft1)
4015 Remote SQL: SELECT c2, (c2 % 2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1
4018 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;
4033 explain (verbose, costs off)
4034 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;
4036 ---------------------------------------------------------------------------------------------------
4038 Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2))
4041 Output: c2, array_agg(c2) OVER (?), ((c2 % 2))
4043 Output: c2, ((c2 % 2))
4044 Sort Key: ((ft1.c2 % 2)), ft1.c2
4046 Output: c2, ((c2 % 2))
4047 Relations: Aggregate on (public.ft1)
4048 Remote SQL: SELECT c2, (c2 % 2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1
4051 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;
4066 -- ===================================================================
4067 -- parameterized queries
4068 -- ===================================================================
4070 PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $1 AND t2.c1 = $2;
4071 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2);
4073 ------------------------------------------------------------------------------------------------------------------------------
4075 Output: t1.c3, t2.c3
4076 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
4077 Remote SQL: SELECT r1.c3, r2.c3 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = 2)) AND ((r1."C 1" = 1))))
4086 EXECUTE st1(101, 101);
4092 SET enable_hashjoin TO off;
4093 SET enable_sort TO off;
4094 -- subquery using stable function (can't be sent to remote)
4095 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;
4096 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st2(10, 20);
4098 ----------------------------------------------------------------------------------------------------------------------------------
4099 Nested Loop Semi Join
4100 Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
4101 Join Filter: (t2.c3 = t1.c3)
4102 -> Foreign Scan on public.ft1 t1
4103 Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
4104 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 20)) ORDER BY "C 1" ASC NULLS LAST
4107 -> Foreign Scan on public.ft2 t2
4109 Filter: (date(t2.c4) = '01-17-1970'::date)
4110 Remote SQL: SELECT c3, c4 FROM "S 1"."T 1" WHERE (("C 1" > 10))
4113 EXECUTE st2(10, 20);
4114 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4115 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4116 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo
4119 EXECUTE st2(101, 121);
4120 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4121 -----+----+-------+------------------------------+--------------------------+----+------------+-----
4122 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo
4125 RESET enable_hashjoin;
4127 -- subquery using immutable function (can be sent to remote)
4128 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;
4129 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st3(10, 20);
4131 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4133 Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
4136 Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
4137 Relations: (public.ft1 t1) SEMI JOIN (public.ft2 t2)
4138 Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8 FROM "S 1"."T 1" r1 WHERE ((r1."C 1" < 20)) AND EXISTS (SELECT NULL FROM "S 1"."T 1" r3 WHERE ((r3."C 1" > 10)) AND ((date(r3.c5) = '1970-01-17'::date)) AND ((r3.c3 = r1.c3)))
4141 EXECUTE st3(10, 20);
4142 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4143 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4144 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo
4147 EXECUTE st3(20, 30);
4148 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4149 ----+----+----+----+----+----+----+----
4152 -- custom plan should be chosen initially
4153 PREPARE st4(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 = $1;
4154 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
4156 ---------------------------------------------------------------------------------------------
4157 Foreign Scan on public.ft1 t1
4158 Output: c1, c2, c3, c4, c5, c6, c7, c8
4159 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4162 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
4164 ---------------------------------------------------------------------------------------------
4165 Foreign Scan on public.ft1 t1
4166 Output: c1, c2, c3, c4, c5, c6, c7, c8
4167 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4170 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
4172 ---------------------------------------------------------------------------------------------
4173 Foreign Scan on public.ft1 t1
4174 Output: c1, c2, c3, c4, c5, c6, c7, c8
4175 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4178 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
4180 ---------------------------------------------------------------------------------------------
4181 Foreign Scan on public.ft1 t1
4182 Output: c1, c2, c3, c4, c5, c6, c7, c8
4183 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4186 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
4188 ---------------------------------------------------------------------------------------------
4189 Foreign Scan on public.ft1 t1
4190 Output: c1, c2, c3, c4, c5, c6, c7, c8
4191 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4194 -- once we try it enough times, should switch to generic plan
4195 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
4197 -------------------------------------------------------------------------------------------------------
4198 Foreign Scan on public.ft1 t1
4199 Output: c1, c2, c3, c4, c5, c6, c7, c8
4200 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
4203 -- value of $1 should not be sent to remote
4204 PREPARE st5(user_enum,int) AS SELECT * FROM ft1 t1 WHERE c8 = $1 and c1 = $2;
4205 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4207 ---------------------------------------------------------------------------------------------
4208 Foreign Scan on public.ft1 t1
4209 Output: c1, c2, c3, c4, c5, c6, c7, c8
4210 Filter: (t1.c8 = 'foo'::user_enum)
4211 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4214 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4216 ---------------------------------------------------------------------------------------------
4217 Foreign Scan on public.ft1 t1
4218 Output: c1, c2, c3, c4, c5, c6, c7, c8
4219 Filter: (t1.c8 = 'foo'::user_enum)
4220 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4223 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4225 ---------------------------------------------------------------------------------------------
4226 Foreign Scan on public.ft1 t1
4227 Output: c1, c2, c3, c4, c5, c6, c7, c8
4228 Filter: (t1.c8 = 'foo'::user_enum)
4229 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4232 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4234 ---------------------------------------------------------------------------------------------
4235 Foreign Scan on public.ft1 t1
4236 Output: c1, c2, c3, c4, c5, c6, c7, c8
4237 Filter: (t1.c8 = 'foo'::user_enum)
4238 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4241 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4243 ---------------------------------------------------------------------------------------------
4244 Foreign Scan on public.ft1 t1
4245 Output: c1, c2, c3, c4, c5, c6, c7, c8
4246 Filter: (t1.c8 = 'foo'::user_enum)
4247 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4250 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4252 -------------------------------------------------------------------------------------------------------
4253 Foreign Scan on public.ft1 t1
4254 Output: c1, c2, c3, c4, c5, c6, c7, c8
4255 Filter: (t1.c8 = $1)
4256 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
4259 EXECUTE st5('foo', 1);
4260 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4261 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4262 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4265 -- altering FDW options requires replanning
4266 PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2;
4267 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
4269 ----------------------------------------------------------------------------------------------
4270 Foreign Scan on public.ft1 t1
4271 Output: c1, c2, c3, c4, c5, c6, c7, c8
4272 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = c2))
4275 PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo');
4276 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
4278 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4279 Insert on public.ft1
4280 Remote SQL: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
4283 Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::user_enum
4286 ALTER TABLE "S 1"."T 1" RENAME TO "T 0";
4287 ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 0');
4288 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
4290 ----------------------------------------------------------------------------------------------
4291 Foreign Scan on public.ft1 t1
4292 Output: c1, c2, c3, c4, c5, c6, c7, c8
4293 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 0" WHERE (("C 1" = c2))
4297 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4298 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4299 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4300 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
4301 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
4302 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo
4303 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo
4304 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo
4305 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
4306 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
4307 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo
4310 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
4312 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4313 Insert on public.ft1
4314 Remote SQL: INSERT INTO "S 1"."T 0"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
4317 Output: NULL::integer, 1001, 101, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft1 '::character(10), NULL::user_enum
4320 ALTER TABLE "S 1"."T 0" RENAME TO "T 1";
4321 ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 1');
4322 PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
4323 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
4325 -----------------------------------------------------------------------------------------
4328 Relations: Aggregate on (public.ft1 t1)
4329 Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2))
4332 ALTER SERVER loopback OPTIONS (DROP extensions);
4333 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
4335 -----------------------------------------------------------
4338 -> Foreign Scan on public.ft1 t1
4340 Filter: (t1.c1 === t1.c2)
4341 Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
4350 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
4360 -- System columns, except ctid and oid, should not be sent to remote
4361 EXPLAIN (VERBOSE, COSTS OFF)
4362 SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
4364 -------------------------------------------------------------------------------
4366 Output: c1, c2, c3, c4, c5, c6, c7, c8
4367 -> Foreign Scan on public.ft1 t1
4368 Output: c1, c2, c3, c4, c5, c6, c7, c8
4369 Filter: (t1.tableoid = '1259'::oid)
4370 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
4373 SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1;
4374 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4375 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4376 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4379 EXPLAIN (VERBOSE, COSTS OFF)
4380 SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1;
4382 -----------------------------------------------------------------------------------------
4383 Foreign Scan on public.ft1 t1
4384 Output: (tableoid)::regclass, c1, c2, c3, c4, c5, c6, c7, c8
4385 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" LIMIT 1::bigint
4388 SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1;
4389 tableoid | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4390 ----------+----+----+-------+------------------------------+--------------------------+----+------------+-----
4391 ft1 | 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4394 EXPLAIN (VERBOSE, COSTS OFF)
4395 SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)';
4397 --------------------------------------------------------------------------------------------------
4398 Foreign Scan on public.ft1 t1
4399 Output: c1, c2, c3, c4, c5, c6, c7, c8
4400 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((ctid = '(0,2)'))
4403 SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)';
4404 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4405 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4406 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
4409 EXPLAIN (VERBOSE, COSTS OFF)
4410 SELECT ctid, * FROM ft1 t1 LIMIT 1;
4412 -----------------------------------------------------------------------------------------------
4413 Foreign Scan on public.ft1 t1
4414 Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8
4415 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" LIMIT 1::bigint
4418 SELECT ctid, * FROM ft1 t1 LIMIT 1;
4419 ctid | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4420 -------+----+----+-------+------------------------------+--------------------------+----+------------+-----
4421 (0,1) | 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4424 -- ===================================================================
4425 -- used in PL/pgSQL function
4426 -- ===================================================================
4427 CREATE OR REPLACE FUNCTION f_test(p_c1 int) RETURNS int AS $$
4431 SELECT c1 INTO v_c1 FROM ft1 WHERE c1 = p_c1 LIMIT 1;
4432 PERFORM c1 FROM ft1 WHERE c1 = p_c1 AND p_c1 = v_c1 LIMIT 1;
4435 $$ LANGUAGE plpgsql;
4442 DROP FUNCTION f_test(int);
4443 -- ===================================================================
4445 -- ===================================================================
4446 -- remote table is not created here
4447 CREATE FOREIGN TABLE reindex_foreign (c1 int, c2 int)
4448 SERVER loopback2 OPTIONS (table_name 'reindex_local');
4449 REINDEX TABLE reindex_foreign; -- error
4450 ERROR: "reindex_foreign" is not a table or materialized view
4451 REINDEX TABLE CONCURRENTLY reindex_foreign; -- error
4452 ERROR: "reindex_foreign" is not a table or materialized view
4453 DROP FOREIGN TABLE reindex_foreign;
4454 -- partitions and foreign tables
4455 CREATE TABLE reind_fdw_parent (c1 int) PARTITION BY RANGE (c1);
4456 CREATE TABLE reind_fdw_0_10 PARTITION OF reind_fdw_parent
4457 FOR VALUES FROM (0) TO (10);
4458 CREATE FOREIGN TABLE reind_fdw_10_20 PARTITION OF reind_fdw_parent
4459 FOR VALUES FROM (10) TO (20)
4460 SERVER loopback OPTIONS (table_name 'reind_local_10_20');
4461 REINDEX TABLE reind_fdw_parent; -- ok
4462 REINDEX TABLE CONCURRENTLY reind_fdw_parent; -- ok
4463 DROP TABLE reind_fdw_parent;
4464 -- ===================================================================
4466 -- ===================================================================
4467 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int;
4468 SELECT * FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8) WHERE x1 = 1; -- ERROR
4469 ERROR: invalid input syntax for type integer: "foo"
4470 CONTEXT: column "x8" of foreign table "ftx"
4471 SELECT ftx.x1, ft2.c2, ftx.x8 FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8), ft2
4472 WHERE ftx.x1 = ft2.c1 AND ftx.x1 = 1; -- ERROR
4473 ERROR: invalid input syntax for type integer: "foo"
4474 CONTEXT: column "x8" of foreign table "ftx"
4475 SELECT ftx.x1, ft2.c2, ftx FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8), ft2
4476 WHERE ftx.x1 = ft2.c1 AND ftx.x1 = 1; -- ERROR
4477 ERROR: invalid input syntax for type integer: "foo"
4478 CONTEXT: whole-row reference to foreign table "ftx"
4479 SELECT sum(c2), array_agg(c8) FROM ft1 GROUP BY c8; -- ERROR
4480 ERROR: invalid input syntax for type integer: "foo"
4481 CONTEXT: processing expression at position 2 in select list
4482 ANALYZE ft1; -- ERROR
4483 ERROR: invalid input syntax for type integer: "foo"
4484 CONTEXT: column "c8" of foreign table "ft1"
4485 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum;
4486 -- ===================================================================
4487 -- local type can be different from remote type in some cases,
4488 -- in particular if similarly-named operators do equivalent things
4489 -- ===================================================================
4490 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE text;
4491 EXPLAIN (VERBOSE, COSTS OFF)
4492 SELECT * FROM ft1 WHERE c8 = 'foo' LIMIT 1;
4494 --------------------------------------------------------------------------------------------------------------
4495 Foreign Scan on public.ft1
4496 Output: c1, c2, c3, c4, c5, c6, c7, c8
4497 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c8 = 'foo')) LIMIT 1::bigint
4500 SELECT * FROM ft1 WHERE c8 = 'foo' LIMIT 1;
4501 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4502 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4503 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4506 EXPLAIN (VERBOSE, COSTS OFF)
4507 SELECT * FROM ft1 WHERE 'foo' = c8 LIMIT 1;
4509 --------------------------------------------------------------------------------------------------------------
4510 Foreign Scan on public.ft1
4511 Output: c1, c2, c3, c4, c5, c6, c7, c8
4512 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (('foo' = c8)) LIMIT 1::bigint
4515 SELECT * FROM ft1 WHERE 'foo' = c8 LIMIT 1;
4516 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4517 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4518 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4521 -- we declared c8 to be text locally, but it's still the same type on
4522 -- the remote which will balk if we try to do anything incompatible
4523 -- with that remote type
4524 SELECT * FROM ft1 WHERE c8 LIKE 'foo' LIMIT 1; -- ERROR
4525 ERROR: operator does not exist: public.user_enum ~~ unknown
4526 HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
4527 CONTEXT: remote SQL command: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c8 ~~ 'foo')) LIMIT 1::bigint
4528 SELECT * FROM ft1 WHERE c8::text LIKE 'foo' LIMIT 1; -- ERROR; cast not pushed down
4529 ERROR: operator does not exist: public.user_enum ~~ unknown
4530 HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
4531 CONTEXT: remote SQL command: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c8 ~~ 'foo')) LIMIT 1::bigint
4532 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum;
4533 -- ===================================================================
4535 -- + local/remote error doesn't break cursor
4536 -- ===================================================================
4538 DECLARE c CURSOR FOR SELECT * FROM ft1 ORDER BY c1;
4540 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4541 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4542 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4547 ERROR: syntax error at or near "ERROR"
4552 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4553 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4554 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
4558 SELECT * FROM ft1 WHERE 1 / (c1 - 1) > 0; -- ERROR
4559 ERROR: division by zero
4560 CONTEXT: remote SQL command: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (((1 / ("C 1" - 1)) > 0))
4563 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4564 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4565 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
4568 SELECT * FROM ft1 ORDER BY c1 LIMIT 1;
4569 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4570 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4571 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4575 -- ===================================================================
4576 -- test handling of collations
4577 -- ===================================================================
4578 create table loct3 (f1 text collate "C" unique, f2 text, f3 varchar(10) unique);
4579 create foreign table ft3 (f1 text collate "C", f2 text, f3 varchar(10))
4580 server loopback options (table_name 'loct3', use_remote_estimate 'true');
4581 -- can be sent to remote
4582 explain (verbose, costs off) select * from ft3 where f1 = 'foo';
4584 ------------------------------------------------------------------------
4585 Foreign Scan on public.ft3
4587 Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f1 = 'foo'))
4590 explain (verbose, costs off) select * from ft3 where f1 COLLATE "C" = 'foo';
4592 ------------------------------------------------------------------------
4593 Foreign Scan on public.ft3
4595 Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f1 = 'foo'))
4598 explain (verbose, costs off) select * from ft3 where f2 = 'foo';
4600 ------------------------------------------------------------------------
4601 Foreign Scan on public.ft3
4603 Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f2 = 'foo'))
4606 explain (verbose, costs off) select * from ft3 where f3 = 'foo';
4608 ------------------------------------------------------------------------
4609 Foreign Scan on public.ft3
4611 Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f3 = 'foo'))
4614 explain (verbose, costs off) select * from ft3 f, loct3 l
4615 where f.f3 = l.f3 and l.f1 = 'foo';
4617 --------------------------------------------------------------------------------------------------
4619 Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
4620 -> Index Scan using loct3_f1_key on public.loct3 l
4621 Output: l.f1, l.f2, l.f3
4622 Index Cond: (l.f1 = 'foo'::text)
4623 -> Foreign Scan on public.ft3 f
4624 Output: f.f1, f.f2, f.f3
4625 Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f3 = $1::character varying(10)))
4628 -- can't be sent to remote
4629 explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo';
4631 ---------------------------------------------------
4632 Foreign Scan on public.ft3
4634 Filter: ((ft3.f1)::text = 'foo'::text)
4635 Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4638 explain (verbose, costs off) select * from ft3 where f1 = 'foo' COLLATE "C";
4640 ---------------------------------------------------
4641 Foreign Scan on public.ft3
4643 Filter: (ft3.f1 = 'foo'::text COLLATE "C")
4644 Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4647 explain (verbose, costs off) select * from ft3 where f2 COLLATE "C" = 'foo';
4649 ---------------------------------------------------
4650 Foreign Scan on public.ft3
4652 Filter: ((ft3.f2)::text = 'foo'::text)
4653 Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4656 explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C";
4658 ---------------------------------------------------
4659 Foreign Scan on public.ft3
4661 Filter: (ft3.f2 = 'foo'::text COLLATE "C")
4662 Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4665 explain (verbose, costs off) select * from ft3 f, loct3 l
4666 where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo';
4668 -------------------------------------------------------------
4670 Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
4672 Hash Cond: ((f.f3)::text = (l.f3)::text)
4673 -> Foreign Scan on public.ft3 f
4674 Output: f.f1, f.f2, f.f3
4675 Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4677 Output: l.f1, l.f2, l.f3
4678 -> Index Scan using loct3_f1_key on public.loct3 l
4679 Output: l.f1, l.f2, l.f3
4680 Index Cond: (l.f1 = 'foo'::text)
4683 -- ===================================================================
4684 -- test SEMI-JOIN pushdown
4685 -- ===================================================================
4686 EXPLAIN (verbose, costs off)
4687 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN ft4 ON ft2.c2 = ft4.c1
4689 AND EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)
4692 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4694 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3
4695 Relations: ((public.ft2) INNER JOIN (public.ft4)) SEMI JOIN (public.ft5)
4696 Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8, r2.c1, r2.c2, r2.c3 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 3" r2 ON (((r1.c2 = r2.c1)) AND ((r1."C 1" > 900)))) WHERE EXISTS (SELECT NULL FROM "S 1"."T 4" r4 WHERE ((r1.c2 = r4.c1))) ORDER BY r1."C 1" ASC NULLS LAST
4699 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN ft4 ON ft2.c2 = ft4.c1
4701 AND EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)
4703 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3
4704 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------
4705 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4706 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4707 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4708 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4709 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4710 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4711 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4712 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4713 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4714 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4717 -- The same query, different join order
4718 EXPLAIN (verbose, costs off)
4719 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4720 (SELECT * FROM ft4 WHERE
4721 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4726 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4728 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3
4729 Relations: ((public.ft2) INNER JOIN (public.ft4)) SEMI JOIN (public.ft5)
4730 Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8, r4.c1, r4.c2, r4.c3 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 3" r4 ON (((r1.c2 = r4.c1)) AND ((r1."C 1" > 900)))) WHERE EXISTS (SELECT NULL FROM "S 1"."T 4" r5 WHERE ((r4.c1 = r5.c1))) ORDER BY r1."C 1" ASC NULLS LAST
4733 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4734 (SELECT * FROM ft4 WHERE
4735 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4739 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3
4740 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------
4741 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4742 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4743 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4744 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4745 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4746 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4747 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4748 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4749 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4750 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4754 EXPLAIN (verbose, costs off)
4755 SELECT ft2.*, ft4.* FROM ft2 LEFT JOIN
4756 (SELECT * FROM ft4 WHERE
4757 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4760 ORDER BY ft2.c1 LIMIT 10;
4762 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4764 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3
4765 Relations: (public.ft2) LEFT JOIN ((public.ft4) SEMI JOIN (public.ft5))
4766 Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8, s6.c1, s6.c2, s6.c3 FROM ("S 1"."T 1" r1 LEFT JOIN (SELECT r4.c1, r4.c2, r4.c3 FROM "S 1"."T 3" r4 WHERE EXISTS (SELECT NULL FROM "S 1"."T 4" r5 WHERE ((r4.c1 = r5.c1)))) s6(c1, c2, c3) ON (((r1.c2 = s6.c1)))) WHERE ((r1."C 1" > 900)) ORDER BY r1."C 1" ASC NULLS LAST LIMIT 10::bigint
4769 SELECT ft2.*, ft4.* FROM ft2 LEFT JOIN
4770 (SELECT * FROM ft4 WHERE
4771 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4774 ORDER BY ft2.c1 LIMIT 10;
4775 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3
4776 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------
4777 901 | 1 | 00901 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo | | |
4778 902 | 2 | 00902 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo | | |
4779 903 | 3 | 00903 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo | | |
4780 904 | 4 | 00904 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo | | |
4781 905 | 5 | 00905 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo | | |
4782 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4783 907 | 7 | 00907 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo | | |
4784 908 | 8 | 00908 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo | | |
4785 909 | 9 | 00909 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo | | |
4786 910 | 0 | 00910 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo | | |
4789 -- Several semi-joins per upper level join
4790 EXPLAIN (verbose, costs off)
4791 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4792 (SELECT * FROM ft4 WHERE
4793 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4795 INNER JOIN (SELECT * FROM ft5 WHERE
4796 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft5.c1)) ft5
4799 ORDER BY ft2.c1 LIMIT 10;
4801 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4803 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3
4804 Relations: ((((public.ft2) INNER JOIN (public.ft4)) SEMI JOIN (public.ft5)) INNER JOIN (public.ft5 ft5_1)) SEMI JOIN (public.ft4 ft4_1)
4805 Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8, r6.c1, r6.c2, r6.c3 FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 3" r6 ON (((r1.c2 = r6.c1)) AND ((r1."C 1" > 900)))) INNER JOIN "S 1"."T 4" r8 ON (((r1.c2 <= r8.c1)))) WHERE EXISTS (SELECT NULL FROM "S 1"."T 3" r9 WHERE ((r8.c1 = r9.c1))) AND EXISTS (SELECT NULL FROM "S 1"."T 4" r7 WHERE ((r6.c1 = r7.c1))) ORDER BY r1."C 1" ASC NULLS LAST LIMIT 10::bigint
4808 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4809 (SELECT * FROM ft4 WHERE
4810 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4812 INNER JOIN (SELECT * FROM ft5 WHERE
4813 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft5.c1)) ft5
4816 ORDER BY ft2.c1 LIMIT 10;
4817 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3
4818 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------
4819 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4820 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4821 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4822 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4823 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4824 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4825 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4826 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4827 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4828 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4831 -- Semi-join below Semi-join
4832 EXPLAIN (verbose, costs off)
4833 SELECT ft2.* FROM ft2 WHERE
4835 SELECT c1 FROM ft2 WHERE
4836 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2))
4838 ORDER BY ft2.c1 LIMIT 10;
4840 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4842 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8
4843 Relations: (public.ft2) SEMI JOIN ((public.ft2 ft2_1) SEMI JOIN (public.ft4))
4844 Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8 FROM "S 1"."T 1" r1 WHERE ((r1."C 1" > 900)) AND EXISTS (SELECT NULL FROM "S 1"."T 1" r3 WHERE ((r1."C 1" = r3."C 1")) AND EXISTS (SELECT NULL FROM "S 1"."T 3" r4 WHERE ((r3.c2 = r4.c2)))) ORDER BY r1."C 1" ASC NULLS LAST LIMIT 10::bigint
4847 SELECT ft2.* FROM ft2 WHERE
4849 SELECT c1 FROM ft2 WHERE
4850 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2))
4852 ORDER BY ft2.c1 LIMIT 10;
4853 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4854 -----+----+-------+------------------------------+--------------------------+----+------------+-----
4855 903 | 3 | 00903 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
4856 905 | 5 | 00905 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo
4857 907 | 7 | 00907 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
4858 909 | 9 | 00909 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo
4859 913 | 3 | 00913 | Wed Jan 14 00:00:00 1970 PST | Wed Jan 14 00:00:00 1970 | 3 | 3 | foo
4860 915 | 5 | 00915 | Fri Jan 16 00:00:00 1970 PST | Fri Jan 16 00:00:00 1970 | 5 | 5 | foo
4861 917 | 7 | 00917 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
4862 919 | 9 | 00919 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | 9 | foo
4863 923 | 3 | 00923 | Sat Jan 24 00:00:00 1970 PST | Sat Jan 24 00:00:00 1970 | 3 | 3 | foo
4864 925 | 5 | 00925 | Mon Jan 26 00:00:00 1970 PST | Mon Jan 26 00:00:00 1970 | 5 | 5 | foo
4867 -- Upper level relations shouldn't refer EXISTS() subqueries
4868 EXPLAIN (verbose, costs off)
4869 SELECT * FROM ft2 ftupper WHERE
4871 SELECT c1 FROM ft2 WHERE
4872 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2) AND c1 = ftupper.c1 )
4873 AND ftupper.c1 > 900
4874 ORDER BY ftupper.c1 LIMIT 10;
4876 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4878 Output: ftupper.c1, ftupper.c2, ftupper.c3, ftupper.c4, ftupper.c5, ftupper.c6, ftupper.c7, ftupper.c8
4879 Relations: (public.ft2 ftupper) SEMI JOIN ((public.ft2) SEMI JOIN (public.ft4))
4880 Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8 FROM "S 1"."T 1" r1 WHERE ((r1."C 1" > 900)) AND EXISTS (SELECT NULL FROM "S 1"."T 1" r2 WHERE ((r1."C 1" = r2."C 1")) AND EXISTS (SELECT NULL FROM "S 1"."T 3" r3 WHERE ((r2.c2 = r3.c2)))) ORDER BY r1."C 1" ASC NULLS LAST LIMIT 10::bigint
4883 SELECT * FROM ft2 ftupper WHERE
4885 SELECT c1 FROM ft2 WHERE
4886 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2) AND c1 = ftupper.c1 )
4887 AND ftupper.c1 > 900
4888 ORDER BY ftupper.c1 LIMIT 10;
4889 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4890 -----+----+-------+------------------------------+--------------------------+----+------------+-----
4891 903 | 3 | 00903 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
4892 905 | 5 | 00905 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo
4893 907 | 7 | 00907 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
4894 909 | 9 | 00909 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo
4895 913 | 3 | 00913 | Wed Jan 14 00:00:00 1970 PST | Wed Jan 14 00:00:00 1970 | 3 | 3 | foo
4896 915 | 5 | 00915 | Fri Jan 16 00:00:00 1970 PST | Fri Jan 16 00:00:00 1970 | 5 | 5 | foo
4897 917 | 7 | 00917 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
4898 919 | 9 | 00919 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | 9 | foo
4899 923 | 3 | 00923 | Sat Jan 24 00:00:00 1970 PST | Sat Jan 24 00:00:00 1970 | 3 | 3 | foo
4900 925 | 5 | 00925 | Mon Jan 26 00:00:00 1970 PST | Mon Jan 26 00:00:00 1970 | 5 | 5 | foo
4903 -- EXISTS should be propagated to the highest upper inner join
4904 EXPLAIN (verbose, costs off)
4905 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4906 (SELECT * FROM ft4 WHERE EXISTS (
4907 SELECT 1 FROM ft2 WHERE ft2.c2 = ft4.c2)) ft4
4910 (SELECT * FROM ft2 WHERE EXISTS (
4911 SELECT 1 FROM ft4 WHERE ft2.c2 = ft4.c2)) ft21
4914 ORDER BY ft2.c1 LIMIT 10;
4916 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4918 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3
4919 Relations: ((((public.ft2) INNER JOIN (public.ft4)) SEMI JOIN (public.ft2 ft2_1)) INNER JOIN (public.ft2 ft2_2)) SEMI JOIN (public.ft4 ft4_1)
4920 Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8, r6.c1, r6.c2, r6.c3 FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 3" r6 ON (((r1.c2 = r6.c1)) AND ((r1."C 1" > 900)))) INNER JOIN "S 1"."T 1" r8 ON (((r1.c2 = r8.c2)))) WHERE EXISTS (SELECT NULL FROM "S 1"."T 3" r9 WHERE ((r1.c2 = r9.c2))) AND EXISTS (SELECT NULL FROM "S 1"."T 1" r7 WHERE ((r7.c2 = r6.c2))) ORDER BY r1."C 1" ASC NULLS LAST LIMIT 10::bigint
4923 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4924 (SELECT * FROM ft4 WHERE EXISTS (
4925 SELECT 1 FROM ft2 WHERE ft2.c2 = ft4.c2)) ft4
4928 (SELECT * FROM ft2 WHERE EXISTS (
4929 SELECT 1 FROM ft4 WHERE ft2.c2 = ft4.c2)) ft21
4932 ORDER BY ft2.c1 LIMIT 10;
4933 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3
4934 ----+----+----+----+----+----+----+----+----+----+----
4937 -- Can't push down semi-join with inner rel vars in targetlist
4938 EXPLAIN (verbose, costs off)
4939 SELECT ft1.c1 FROM ft1 JOIN ft2 on ft1.c1 = ft2.c1 WHERE
4941 SELECT ft2.c1 FROM ft2 JOIN ft4 ON ft2.c1 = ft4.c1)
4942 ORDER BY ft1.c1 LIMIT 5;
4944 -------------------------------------------------------------------------------------------------------------------------------------------------------------------
4949 Merge Cond: (ft1.c1 = ft2_1.c1)
4951 Output: ft1.c1, ft2.c1
4952 Relations: (public.ft1) INNER JOIN (public.ft2)
4953 Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2."C 1" = r1."C 1")))) ORDER BY r1."C 1" ASC NULLS LAST
4955 Output: ft2_1.c1, ft4.c1
4956 Relations: (public.ft2 ft2_1) INNER JOIN (public.ft4)
4957 Remote SQL: SELECT r5."C 1", r6.c1 FROM ("S 1"."T 1" r5 INNER JOIN "S 1"."T 3" r6 ON (((r5."C 1" = r6.c1)))) ORDER BY r5."C 1" ASC NULLS LAST
4960 -- ===================================================================
4961 -- test writable foreign table stuff
4962 -- ===================================================================
4963 EXPLAIN (verbose, costs off)
4964 INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
4966 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4967 Insert on public.ft2
4968 Remote SQL: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
4970 -> Subquery Scan on "*SELECT*"
4971 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::user_enum
4972 -> Foreign Scan on public.ft2 ft2_1
4973 Output: (ft2_1.c1 + 1000), (ft2_1.c2 + 100), (ft2_1.c3 || ft2_1.c3)
4974 Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1" LIMIT 20::bigint
4977 INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
4978 INSERT INTO ft2 (c1,c2,c3)
4979 VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING *;
4980 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4981 ------+-----+-----+----+----+----+------------+----
4982 1101 | 201 | aaa | | | | ft2 |
4983 1102 | 202 | bbb | | | | ft2 |
4984 1103 | 203 | ccc | | | | ft2 |
4987 INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee');
4988 EXPLAIN (verbose, costs off)
4989 UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; -- can be pushed down
4991 ----------------------------------------------------------------------------------------------------------------
4992 Update on public.ft2
4993 -> Foreign Update on public.ft2
4994 Remote SQL: UPDATE "S 1"."T 1" SET c2 = (c2 + 300), c3 = (c3 || '_update3') WHERE ((("C 1" % 10) = 3))
4997 UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3;
4998 EXPLAIN (verbose, costs off)
4999 UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *; -- can be pushed down
5001 ------------------------------------------------------------------------------------------------------------------------------------------------------------
5002 Update on public.ft2
5003 Output: c1, c2, c3, c4, c5, c6, c7, c8
5004 -> Foreign Update on public.ft2
5005 Remote SQL: UPDATE "S 1"."T 1" SET c2 = (c2 + 400), c3 = (c3 || '_update7') WHERE ((("C 1" % 10) = 7)) RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8
5008 UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *;
5009 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
5010 ------+-----+--------------------+------------------------------+--------------------------+----+------------+-----
5011 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5012 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5013 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5014 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5015 47 | 407 | 00047_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5016 57 | 407 | 00057_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5017 67 | 407 | 00067_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5018 77 | 407 | 00077_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5019 87 | 407 | 00087_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5020 97 | 407 | 00097_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5021 107 | 407 | 00107_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5022 117 | 407 | 00117_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5023 127 | 407 | 00127_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5024 137 | 407 | 00137_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5025 147 | 407 | 00147_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5026 157 | 407 | 00157_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5027 167 | 407 | 00167_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5028 177 | 407 | 00177_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5029 187 | 407 | 00187_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5030 197 | 407 | 00197_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5031 207 | 407 | 00207_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5032 217 | 407 | 00217_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5033 227 | 407 | 00227_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5034 237 | 407 | 00237_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5035 247 | 407 | 00247_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5036 257 | 407 | 00257_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5037 267 | 407 | 00267_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5038 277 | 407 | 00277_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5039 287 | 407 | 00287_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5040 297 | 407 | 00297_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5041 307 | 407 | 00307_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5042 317 | 407 | 00317_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5043 327 | 407 | 00327_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5044 337 | 407 | 00337_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5045 347 | 407 | 00347_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5046 357 | 407 | 00357_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5047 367 | 407 | 00367_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5048 377 | 407 | 00377_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5049 387 | 407 | 00387_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5050 397 | 407 | 00397_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5051 407 | 407 | 00407_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5052 417 | 407 | 00417_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5053 427 | 407 | 00427_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5054 437 | 407 | 00437_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5055 447 | 407 | 00447_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5056 457 | 407 | 00457_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5057 467 | 407 | 00467_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5058 477 | 407 | 00477_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5059 487 | 407 | 00487_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5060 497 | 407 | 00497_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5061 507 | 407 | 00507_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5062 517 | 407 | 00517_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5063 527 | 407 | 00527_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5064 537 | 407 | 00537_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5065 547 | 407 | 00547_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5066 557 | 407 | 00557_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5067 567 | 407 | 00567_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5068 577 | 407 | 00577_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5069 587 | 407 | 00587_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5070 597 | 407 | 00597_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5071 607 | 407 | 00607_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5072 617 | 407 | 00617_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5073 627 | 407 | 00627_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5074 637 | 407 | 00637_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5075 647 | 407 | 00647_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5076 657 | 407 | 00657_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5077 667 | 407 | 00667_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5078 677 | 407 | 00677_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5079 687 | 407 | 00687_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5080 697 | 407 | 00697_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5081 707 | 407 | 00707_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5082 717 | 407 | 00717_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5083 727 | 407 | 00727_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5084 737 | 407 | 00737_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5085 747 | 407 | 00747_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5086 757 | 407 | 00757_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5087 767 | 407 | 00767_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5088 777 | 407 | 00777_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5089 787 | 407 | 00787_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5090 797 | 407 | 00797_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5091 807 | 407 | 00807_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5092 817 | 407 | 00817_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5093 827 | 407 | 00827_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5094 837 | 407 | 00837_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5095 847 | 407 | 00847_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5096 857 | 407 | 00857_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5097 867 | 407 | 00867_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5098 877 | 407 | 00877_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5099 887 | 407 | 00887_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5100 897 | 407 | 00897_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5101 907 | 407 | 00907_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5102 917 | 407 | 00917_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5103 927 | 407 | 00927_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5104 937 | 407 | 00937_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5105 947 | 407 | 00947_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5106 957 | 407 | 00957_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5107 967 | 407 | 00967_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5108 977 | 407 | 00977_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5109 987 | 407 | 00987_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5110 997 | 407 | 00997_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5111 1007 | 507 | 0000700007_update7 | | | | ft2 |
5112 1017 | 507 | 0001700017_update7 | | | | ft2 |
5115 EXPLAIN (verbose, costs off)
5116 UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
5117 FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down
5119 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5120 Update on public.ft2
5122 Remote SQL: UPDATE "S 1"."T 1" r1 SET c2 = (r1.c2 + 500), c3 = (r1.c3 || '_update9'), c7 = 'ft2 '::character(10) FROM "S 1"."T 1" r2 WHERE ((r1.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 9))
5125 UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
5126 FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9;
5127 EXPLAIN (verbose, costs off)
5128 DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4; -- can be pushed down
5130 --------------------------------------------------------------------------------------------
5131 Delete on public.ft2
5133 -> Foreign Delete on public.ft2
5134 Remote SQL: DELETE FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 5)) RETURNING "C 1", c4
5137 DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4;
5139 ------+------------------------------
5140 5 | Tue Jan 06 00:00:00 1970 PST
5141 15 | Fri Jan 16 00:00:00 1970 PST
5142 25 | Mon Jan 26 00:00:00 1970 PST
5143 35 | Thu Feb 05 00:00:00 1970 PST
5144 45 | Sun Feb 15 00:00:00 1970 PST
5145 55 | Wed Feb 25 00:00:00 1970 PST
5146 65 | Sat Mar 07 00:00:00 1970 PST
5147 75 | Tue Mar 17 00:00:00 1970 PST
5148 85 | Fri Mar 27 00:00:00 1970 PST
5149 95 | Mon Apr 06 00:00:00 1970 PST
5150 105 | Tue Jan 06 00:00:00 1970 PST
5151 115 | Fri Jan 16 00:00:00 1970 PST
5152 125 | Mon Jan 26 00:00:00 1970 PST
5153 135 | Thu Feb 05 00:00:00 1970 PST
5154 145 | Sun Feb 15 00:00:00 1970 PST
5155 155 | Wed Feb 25 00:00:00 1970 PST
5156 165 | Sat Mar 07 00:00:00 1970 PST
5157 175 | Tue Mar 17 00:00:00 1970 PST
5158 185 | Fri Mar 27 00:00:00 1970 PST
5159 195 | Mon Apr 06 00:00:00 1970 PST
5160 205 | Tue Jan 06 00:00:00 1970 PST
5161 215 | Fri Jan 16 00:00:00 1970 PST
5162 225 | Mon Jan 26 00:00:00 1970 PST
5163 235 | Thu Feb 05 00:00:00 1970 PST
5164 245 | Sun Feb 15 00:00:00 1970 PST
5165 255 | Wed Feb 25 00:00:00 1970 PST
5166 265 | Sat Mar 07 00:00:00 1970 PST
5167 275 | Tue Mar 17 00:00:00 1970 PST
5168 285 | Fri Mar 27 00:00:00 1970 PST
5169 295 | Mon Apr 06 00:00:00 1970 PST
5170 305 | Tue Jan 06 00:00:00 1970 PST
5171 315 | Fri Jan 16 00:00:00 1970 PST
5172 325 | Mon Jan 26 00:00:00 1970 PST
5173 335 | Thu Feb 05 00:00:00 1970 PST
5174 345 | Sun Feb 15 00:00:00 1970 PST
5175 355 | Wed Feb 25 00:00:00 1970 PST
5176 365 | Sat Mar 07 00:00:00 1970 PST
5177 375 | Tue Mar 17 00:00:00 1970 PST
5178 385 | Fri Mar 27 00:00:00 1970 PST
5179 395 | Mon Apr 06 00:00:00 1970 PST
5180 405 | Tue Jan 06 00:00:00 1970 PST
5181 415 | Fri Jan 16 00:00:00 1970 PST
5182 425 | Mon Jan 26 00:00:00 1970 PST
5183 435 | Thu Feb 05 00:00:00 1970 PST
5184 445 | Sun Feb 15 00:00:00 1970 PST
5185 455 | Wed Feb 25 00:00:00 1970 PST
5186 465 | Sat Mar 07 00:00:00 1970 PST
5187 475 | Tue Mar 17 00:00:00 1970 PST
5188 485 | Fri Mar 27 00:00:00 1970 PST
5189 495 | Mon Apr 06 00:00:00 1970 PST
5190 505 | Tue Jan 06 00:00:00 1970 PST
5191 515 | Fri Jan 16 00:00:00 1970 PST
5192 525 | Mon Jan 26 00:00:00 1970 PST
5193 535 | Thu Feb 05 00:00:00 1970 PST
5194 545 | Sun Feb 15 00:00:00 1970 PST
5195 555 | Wed Feb 25 00:00:00 1970 PST
5196 565 | Sat Mar 07 00:00:00 1970 PST
5197 575 | Tue Mar 17 00:00:00 1970 PST
5198 585 | Fri Mar 27 00:00:00 1970 PST
5199 595 | Mon Apr 06 00:00:00 1970 PST
5200 605 | Tue Jan 06 00:00:00 1970 PST
5201 615 | Fri Jan 16 00:00:00 1970 PST
5202 625 | Mon Jan 26 00:00:00 1970 PST
5203 635 | Thu Feb 05 00:00:00 1970 PST
5204 645 | Sun Feb 15 00:00:00 1970 PST
5205 655 | Wed Feb 25 00:00:00 1970 PST
5206 665 | Sat Mar 07 00:00:00 1970 PST
5207 675 | Tue Mar 17 00:00:00 1970 PST
5208 685 | Fri Mar 27 00:00:00 1970 PST
5209 695 | Mon Apr 06 00:00:00 1970 PST
5210 705 | Tue Jan 06 00:00:00 1970 PST
5211 715 | Fri Jan 16 00:00:00 1970 PST
5212 725 | Mon Jan 26 00:00:00 1970 PST
5213 735 | Thu Feb 05 00:00:00 1970 PST
5214 745 | Sun Feb 15 00:00:00 1970 PST
5215 755 | Wed Feb 25 00:00:00 1970 PST
5216 765 | Sat Mar 07 00:00:00 1970 PST
5217 775 | Tue Mar 17 00:00:00 1970 PST
5218 785 | Fri Mar 27 00:00:00 1970 PST
5219 795 | Mon Apr 06 00:00:00 1970 PST
5220 805 | Tue Jan 06 00:00:00 1970 PST
5221 815 | Fri Jan 16 00:00:00 1970 PST
5222 825 | Mon Jan 26 00:00:00 1970 PST
5223 835 | Thu Feb 05 00:00:00 1970 PST
5224 845 | Sun Feb 15 00:00:00 1970 PST
5225 855 | Wed Feb 25 00:00:00 1970 PST
5226 865 | Sat Mar 07 00:00:00 1970 PST
5227 875 | Tue Mar 17 00:00:00 1970 PST
5228 885 | Fri Mar 27 00:00:00 1970 PST
5229 895 | Mon Apr 06 00:00:00 1970 PST
5230 905 | Tue Jan 06 00:00:00 1970 PST
5231 915 | Fri Jan 16 00:00:00 1970 PST
5232 925 | Mon Jan 26 00:00:00 1970 PST
5233 935 | Thu Feb 05 00:00:00 1970 PST
5234 945 | Sun Feb 15 00:00:00 1970 PST
5235 955 | Wed Feb 25 00:00:00 1970 PST
5236 965 | Sat Mar 07 00:00:00 1970 PST
5237 975 | Tue Mar 17 00:00:00 1970 PST
5238 985 | Fri Mar 27 00:00:00 1970 PST
5239 995 | Mon Apr 06 00:00:00 1970 PST
5245 EXPLAIN (verbose, costs off)
5246 DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down
5248 ----------------------------------------------------------------------------------------------------------------------------
5249 Delete on public.ft2
5251 Remote SQL: DELETE FROM "S 1"."T 1" r1 USING "S 1"."T 1" r2 WHERE ((r1.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 2))
5254 DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;
5255 SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1;
5257 ------+-----+--------------------+------------------------------
5258 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST
5259 3 | 303 | 00003_update3 | Sun Jan 04 00:00:00 1970 PST
5260 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST
5261 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST
5262 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST
5263 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST
5264 9 | 509 | 00009_update9 | Sat Jan 10 00:00:00 1970 PST
5265 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST
5266 11 | 1 | 00011 | Mon Jan 12 00:00:00 1970 PST
5267 13 | 303 | 00013_update3 | Wed Jan 14 00:00:00 1970 PST
5268 14 | 4 | 00014 | Thu Jan 15 00:00:00 1970 PST
5269 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST
5270 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST
5271 18 | 8 | 00018 | Mon Jan 19 00:00:00 1970 PST
5272 19 | 509 | 00019_update9 | Tue Jan 20 00:00:00 1970 PST
5273 20 | 0 | 00020 | Wed Jan 21 00:00:00 1970 PST
5274 21 | 1 | 00021 | Thu Jan 22 00:00:00 1970 PST
5275 23 | 303 | 00023_update3 | Sat Jan 24 00:00:00 1970 PST
5276 24 | 4 | 00024 | Sun Jan 25 00:00:00 1970 PST
5277 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST
5278 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST
5279 28 | 8 | 00028 | Thu Jan 29 00:00:00 1970 PST
5280 29 | 509 | 00029_update9 | Fri Jan 30 00:00:00 1970 PST
5281 30 | 0 | 00030 | Sat Jan 31 00:00:00 1970 PST
5282 31 | 1 | 00031 | Sun Feb 01 00:00:00 1970 PST
5283 33 | 303 | 00033_update3 | Tue Feb 03 00:00:00 1970 PST
5284 34 | 4 | 00034 | Wed Feb 04 00:00:00 1970 PST
5285 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST
5286 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST
5287 38 | 8 | 00038 | Sun Feb 08 00:00:00 1970 PST
5288 39 | 509 | 00039_update9 | Mon Feb 09 00:00:00 1970 PST
5289 40 | 0 | 00040 | Tue Feb 10 00:00:00 1970 PST
5290 41 | 1 | 00041 | Wed Feb 11 00:00:00 1970 PST
5291 43 | 303 | 00043_update3 | Fri Feb 13 00:00:00 1970 PST
5292 44 | 4 | 00044 | Sat Feb 14 00:00:00 1970 PST
5293 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST
5294 47 | 407 | 00047_update7 | Tue Feb 17 00:00:00 1970 PST
5295 48 | 8 | 00048 | Wed Feb 18 00:00:00 1970 PST
5296 49 | 509 | 00049_update9 | Thu Feb 19 00:00:00 1970 PST
5297 50 | 0 | 00050 | Fri Feb 20 00:00:00 1970 PST
5298 51 | 1 | 00051 | Sat Feb 21 00:00:00 1970 PST
5299 53 | 303 | 00053_update3 | Mon Feb 23 00:00:00 1970 PST
5300 54 | 4 | 00054 | Tue Feb 24 00:00:00 1970 PST
5301 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST
5302 57 | 407 | 00057_update7 | Fri Feb 27 00:00:00 1970 PST
5303 58 | 8 | 00058 | Sat Feb 28 00:00:00 1970 PST
5304 59 | 509 | 00059_update9 | Sun Mar 01 00:00:00 1970 PST
5305 60 | 0 | 00060 | Mon Mar 02 00:00:00 1970 PST
5306 61 | 1 | 00061 | Tue Mar 03 00:00:00 1970 PST
5307 63 | 303 | 00063_update3 | Thu Mar 05 00:00:00 1970 PST
5308 64 | 4 | 00064 | Fri Mar 06 00:00:00 1970 PST
5309 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST
5310 67 | 407 | 00067_update7 | Mon Mar 09 00:00:00 1970 PST
5311 68 | 8 | 00068 | Tue Mar 10 00:00:00 1970 PST
5312 69 | 509 | 00069_update9 | Wed Mar 11 00:00:00 1970 PST
5313 70 | 0 | 00070 | Thu Mar 12 00:00:00 1970 PST
5314 71 | 1 | 00071 | Fri Mar 13 00:00:00 1970 PST
5315 73 | 303 | 00073_update3 | Sun Mar 15 00:00:00 1970 PST
5316 74 | 4 | 00074 | Mon Mar 16 00:00:00 1970 PST
5317 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST
5318 77 | 407 | 00077_update7 | Thu Mar 19 00:00:00 1970 PST
5319 78 | 8 | 00078 | Fri Mar 20 00:00:00 1970 PST
5320 79 | 509 | 00079_update9 | Sat Mar 21 00:00:00 1970 PST
5321 80 | 0 | 00080 | Sun Mar 22 00:00:00 1970 PST
5322 81 | 1 | 00081 | Mon Mar 23 00:00:00 1970 PST
5323 83 | 303 | 00083_update3 | Wed Mar 25 00:00:00 1970 PST
5324 84 | 4 | 00084 | Thu Mar 26 00:00:00 1970 PST
5325 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST
5326 87 | 407 | 00087_update7 | Sun Mar 29 00:00:00 1970 PST
5327 88 | 8 | 00088 | Mon Mar 30 00:00:00 1970 PST
5328 89 | 509 | 00089_update9 | Tue Mar 31 00:00:00 1970 PST
5329 90 | 0 | 00090 | Wed Apr 01 00:00:00 1970 PST
5330 91 | 1 | 00091 | Thu Apr 02 00:00:00 1970 PST
5331 93 | 303 | 00093_update3 | Sat Apr 04 00:00:00 1970 PST
5332 94 | 4 | 00094 | Sun Apr 05 00:00:00 1970 PST
5333 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST
5334 97 | 407 | 00097_update7 | Wed Apr 08 00:00:00 1970 PST
5335 98 | 8 | 00098 | Thu Apr 09 00:00:00 1970 PST
5336 99 | 509 | 00099_update9 | Fri Apr 10 00:00:00 1970 PST
5337 100 | 0 | 00100 | Thu Jan 01 00:00:00 1970 PST
5338 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST
5339 103 | 303 | 00103_update3 | Sun Jan 04 00:00:00 1970 PST
5340 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST
5341 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST
5342 107 | 407 | 00107_update7 | Thu Jan 08 00:00:00 1970 PST
5343 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST
5344 109 | 509 | 00109_update9 | Sat Jan 10 00:00:00 1970 PST
5345 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST
5346 111 | 1 | 00111 | Mon Jan 12 00:00:00 1970 PST
5347 113 | 303 | 00113_update3 | Wed Jan 14 00:00:00 1970 PST
5348 114 | 4 | 00114 | Thu Jan 15 00:00:00 1970 PST
5349 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST
5350 117 | 407 | 00117_update7 | Sun Jan 18 00:00:00 1970 PST
5351 118 | 8 | 00118 | Mon Jan 19 00:00:00 1970 PST
5352 119 | 509 | 00119_update9 | Tue Jan 20 00:00:00 1970 PST
5353 120 | 0 | 00120 | Wed Jan 21 00:00:00 1970 PST
5354 121 | 1 | 00121 | Thu Jan 22 00:00:00 1970 PST
5355 123 | 303 | 00123_update3 | Sat Jan 24 00:00:00 1970 PST
5356 124 | 4 | 00124 | Sun Jan 25 00:00:00 1970 PST
5357 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST
5358 127 | 407 | 00127_update7 | Wed Jan 28 00:00:00 1970 PST
5359 128 | 8 | 00128 | Thu Jan 29 00:00:00 1970 PST
5360 129 | 509 | 00129_update9 | Fri Jan 30 00:00:00 1970 PST
5361 130 | 0 | 00130 | Sat Jan 31 00:00:00 1970 PST
5362 131 | 1 | 00131 | Sun Feb 01 00:00:00 1970 PST
5363 133 | 303 | 00133_update3 | Tue Feb 03 00:00:00 1970 PST
5364 134 | 4 | 00134 | Wed Feb 04 00:00:00 1970 PST
5365 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST
5366 137 | 407 | 00137_update7 | Sat Feb 07 00:00:00 1970 PST
5367 138 | 8 | 00138 | Sun Feb 08 00:00:00 1970 PST
5368 139 | 509 | 00139_update9 | Mon Feb 09 00:00:00 1970 PST
5369 140 | 0 | 00140 | Tue Feb 10 00:00:00 1970 PST
5370 141 | 1 | 00141 | Wed Feb 11 00:00:00 1970 PST
5371 143 | 303 | 00143_update3 | Fri Feb 13 00:00:00 1970 PST
5372 144 | 4 | 00144 | Sat Feb 14 00:00:00 1970 PST
5373 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST
5374 147 | 407 | 00147_update7 | Tue Feb 17 00:00:00 1970 PST
5375 148 | 8 | 00148 | Wed Feb 18 00:00:00 1970 PST
5376 149 | 509 | 00149_update9 | Thu Feb 19 00:00:00 1970 PST
5377 150 | 0 | 00150 | Fri Feb 20 00:00:00 1970 PST
5378 151 | 1 | 00151 | Sat Feb 21 00:00:00 1970 PST
5379 153 | 303 | 00153_update3 | Mon Feb 23 00:00:00 1970 PST
5380 154 | 4 | 00154 | Tue Feb 24 00:00:00 1970 PST
5381 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST
5382 157 | 407 | 00157_update7 | Fri Feb 27 00:00:00 1970 PST
5383 158 | 8 | 00158 | Sat Feb 28 00:00:00 1970 PST
5384 159 | 509 | 00159_update9 | Sun Mar 01 00:00:00 1970 PST
5385 160 | 0 | 00160 | Mon Mar 02 00:00:00 1970 PST
5386 161 | 1 | 00161 | Tue Mar 03 00:00:00 1970 PST
5387 163 | 303 | 00163_update3 | Thu Mar 05 00:00:00 1970 PST
5388 164 | 4 | 00164 | Fri Mar 06 00:00:00 1970 PST
5389 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST
5390 167 | 407 | 00167_update7 | Mon Mar 09 00:00:00 1970 PST
5391 168 | 8 | 00168 | Tue Mar 10 00:00:00 1970 PST
5392 169 | 509 | 00169_update9 | Wed Mar 11 00:00:00 1970 PST
5393 170 | 0 | 00170 | Thu Mar 12 00:00:00 1970 PST
5394 171 | 1 | 00171 | Fri Mar 13 00:00:00 1970 PST
5395 173 | 303 | 00173_update3 | Sun Mar 15 00:00:00 1970 PST
5396 174 | 4 | 00174 | Mon Mar 16 00:00:00 1970 PST
5397 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST
5398 177 | 407 | 00177_update7 | Thu Mar 19 00:00:00 1970 PST
5399 178 | 8 | 00178 | Fri Mar 20 00:00:00 1970 PST
5400 179 | 509 | 00179_update9 | Sat Mar 21 00:00:00 1970 PST
5401 180 | 0 | 00180 | Sun Mar 22 00:00:00 1970 PST
5402 181 | 1 | 00181 | Mon Mar 23 00:00:00 1970 PST
5403 183 | 303 | 00183_update3 | Wed Mar 25 00:00:00 1970 PST
5404 184 | 4 | 00184 | Thu Mar 26 00:00:00 1970 PST
5405 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST
5406 187 | 407 | 00187_update7 | Sun Mar 29 00:00:00 1970 PST
5407 188 | 8 | 00188 | Mon Mar 30 00:00:00 1970 PST
5408 189 | 509 | 00189_update9 | Tue Mar 31 00:00:00 1970 PST
5409 190 | 0 | 00190 | Wed Apr 01 00:00:00 1970 PST
5410 191 | 1 | 00191 | Thu Apr 02 00:00:00 1970 PST
5411 193 | 303 | 00193_update3 | Sat Apr 04 00:00:00 1970 PST
5412 194 | 4 | 00194 | Sun Apr 05 00:00:00 1970 PST
5413 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST
5414 197 | 407 | 00197_update7 | Wed Apr 08 00:00:00 1970 PST
5415 198 | 8 | 00198 | Thu Apr 09 00:00:00 1970 PST
5416 199 | 509 | 00199_update9 | Fri Apr 10 00:00:00 1970 PST
5417 200 | 0 | 00200 | Thu Jan 01 00:00:00 1970 PST
5418 201 | 1 | 00201 | Fri Jan 02 00:00:00 1970 PST
5419 203 | 303 | 00203_update3 | Sun Jan 04 00:00:00 1970 PST
5420 204 | 4 | 00204 | Mon Jan 05 00:00:00 1970 PST
5421 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST
5422 207 | 407 | 00207_update7 | Thu Jan 08 00:00:00 1970 PST
5423 208 | 8 | 00208 | Fri Jan 09 00:00:00 1970 PST
5424 209 | 509 | 00209_update9 | Sat Jan 10 00:00:00 1970 PST
5425 210 | 0 | 00210 | Sun Jan 11 00:00:00 1970 PST
5426 211 | 1 | 00211 | Mon Jan 12 00:00:00 1970 PST
5427 213 | 303 | 00213_update3 | Wed Jan 14 00:00:00 1970 PST
5428 214 | 4 | 00214 | Thu Jan 15 00:00:00 1970 PST
5429 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST
5430 217 | 407 | 00217_update7 | Sun Jan 18 00:00:00 1970 PST
5431 218 | 8 | 00218 | Mon Jan 19 00:00:00 1970 PST
5432 219 | 509 | 00219_update9 | Tue Jan 20 00:00:00 1970 PST
5433 220 | 0 | 00220 | Wed Jan 21 00:00:00 1970 PST
5434 221 | 1 | 00221 | Thu Jan 22 00:00:00 1970 PST
5435 223 | 303 | 00223_update3 | Sat Jan 24 00:00:00 1970 PST
5436 224 | 4 | 00224 | Sun Jan 25 00:00:00 1970 PST
5437 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST
5438 227 | 407 | 00227_update7 | Wed Jan 28 00:00:00 1970 PST
5439 228 | 8 | 00228 | Thu Jan 29 00:00:00 1970 PST
5440 229 | 509 | 00229_update9 | Fri Jan 30 00:00:00 1970 PST
5441 230 | 0 | 00230 | Sat Jan 31 00:00:00 1970 PST
5442 231 | 1 | 00231 | Sun Feb 01 00:00:00 1970 PST
5443 233 | 303 | 00233_update3 | Tue Feb 03 00:00:00 1970 PST
5444 234 | 4 | 00234 | Wed Feb 04 00:00:00 1970 PST
5445 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST
5446 237 | 407 | 00237_update7 | Sat Feb 07 00:00:00 1970 PST
5447 238 | 8 | 00238 | Sun Feb 08 00:00:00 1970 PST
5448 239 | 509 | 00239_update9 | Mon Feb 09 00:00:00 1970 PST
5449 240 | 0 | 00240 | Tue Feb 10 00:00:00 1970 PST
5450 241 | 1 | 00241 | Wed Feb 11 00:00:00 1970 PST
5451 243 | 303 | 00243_update3 | Fri Feb 13 00:00:00 1970 PST
5452 244 | 4 | 00244 | Sat Feb 14 00:00:00 1970 PST
5453 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST
5454 247 | 407 | 00247_update7 | Tue Feb 17 00:00:00 1970 PST
5455 248 | 8 | 00248 | Wed Feb 18 00:00:00 1970 PST
5456 249 | 509 | 00249_update9 | Thu Feb 19 00:00:00 1970 PST
5457 250 | 0 | 00250 | Fri Feb 20 00:00:00 1970 PST
5458 251 | 1 | 00251 | Sat Feb 21 00:00:00 1970 PST
5459 253 | 303 | 00253_update3 | Mon Feb 23 00:00:00 1970 PST
5460 254 | 4 | 00254 | Tue Feb 24 00:00:00 1970 PST
5461 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST
5462 257 | 407 | 00257_update7 | Fri Feb 27 00:00:00 1970 PST
5463 258 | 8 | 00258 | Sat Feb 28 00:00:00 1970 PST
5464 259 | 509 | 00259_update9 | Sun Mar 01 00:00:00 1970 PST
5465 260 | 0 | 00260 | Mon Mar 02 00:00:00 1970 PST
5466 261 | 1 | 00261 | Tue Mar 03 00:00:00 1970 PST
5467 263 | 303 | 00263_update3 | Thu Mar 05 00:00:00 1970 PST
5468 264 | 4 | 00264 | Fri Mar 06 00:00:00 1970 PST
5469 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST
5470 267 | 407 | 00267_update7 | Mon Mar 09 00:00:00 1970 PST
5471 268 | 8 | 00268 | Tue Mar 10 00:00:00 1970 PST
5472 269 | 509 | 00269_update9 | Wed Mar 11 00:00:00 1970 PST
5473 270 | 0 | 00270 | Thu Mar 12 00:00:00 1970 PST
5474 271 | 1 | 00271 | Fri Mar 13 00:00:00 1970 PST
5475 273 | 303 | 00273_update3 | Sun Mar 15 00:00:00 1970 PST
5476 274 | 4 | 00274 | Mon Mar 16 00:00:00 1970 PST
5477 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST
5478 277 | 407 | 00277_update7 | Thu Mar 19 00:00:00 1970 PST
5479 278 | 8 | 00278 | Fri Mar 20 00:00:00 1970 PST
5480 279 | 509 | 00279_update9 | Sat Mar 21 00:00:00 1970 PST
5481 280 | 0 | 00280 | Sun Mar 22 00:00:00 1970 PST
5482 281 | 1 | 00281 | Mon Mar 23 00:00:00 1970 PST
5483 283 | 303 | 00283_update3 | Wed Mar 25 00:00:00 1970 PST
5484 284 | 4 | 00284 | Thu Mar 26 00:00:00 1970 PST
5485 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST
5486 287 | 407 | 00287_update7 | Sun Mar 29 00:00:00 1970 PST
5487 288 | 8 | 00288 | Mon Mar 30 00:00:00 1970 PST
5488 289 | 509 | 00289_update9 | Tue Mar 31 00:00:00 1970 PST
5489 290 | 0 | 00290 | Wed Apr 01 00:00:00 1970 PST
5490 291 | 1 | 00291 | Thu Apr 02 00:00:00 1970 PST
5491 293 | 303 | 00293_update3 | Sat Apr 04 00:00:00 1970 PST
5492 294 | 4 | 00294 | Sun Apr 05 00:00:00 1970 PST
5493 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST
5494 297 | 407 | 00297_update7 | Wed Apr 08 00:00:00 1970 PST
5495 298 | 8 | 00298 | Thu Apr 09 00:00:00 1970 PST
5496 299 | 509 | 00299_update9 | Fri Apr 10 00:00:00 1970 PST
5497 300 | 0 | 00300 | Thu Jan 01 00:00:00 1970 PST
5498 301 | 1 | 00301 | Fri Jan 02 00:00:00 1970 PST
5499 303 | 303 | 00303_update3 | Sun Jan 04 00:00:00 1970 PST
5500 304 | 4 | 00304 | Mon Jan 05 00:00:00 1970 PST
5501 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST
5502 307 | 407 | 00307_update7 | Thu Jan 08 00:00:00 1970 PST
5503 308 | 8 | 00308 | Fri Jan 09 00:00:00 1970 PST
5504 309 | 509 | 00309_update9 | Sat Jan 10 00:00:00 1970 PST
5505 310 | 0 | 00310 | Sun Jan 11 00:00:00 1970 PST
5506 311 | 1 | 00311 | Mon Jan 12 00:00:00 1970 PST
5507 313 | 303 | 00313_update3 | Wed Jan 14 00:00:00 1970 PST
5508 314 | 4 | 00314 | Thu Jan 15 00:00:00 1970 PST
5509 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST
5510 317 | 407 | 00317_update7 | Sun Jan 18 00:00:00 1970 PST
5511 318 | 8 | 00318 | Mon Jan 19 00:00:00 1970 PST
5512 319 | 509 | 00319_update9 | Tue Jan 20 00:00:00 1970 PST
5513 320 | 0 | 00320 | Wed Jan 21 00:00:00 1970 PST
5514 321 | 1 | 00321 | Thu Jan 22 00:00:00 1970 PST
5515 323 | 303 | 00323_update3 | Sat Jan 24 00:00:00 1970 PST
5516 324 | 4 | 00324 | Sun Jan 25 00:00:00 1970 PST
5517 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST
5518 327 | 407 | 00327_update7 | Wed Jan 28 00:00:00 1970 PST
5519 328 | 8 | 00328 | Thu Jan 29 00:00:00 1970 PST
5520 329 | 509 | 00329_update9 | Fri Jan 30 00:00:00 1970 PST
5521 330 | 0 | 00330 | Sat Jan 31 00:00:00 1970 PST
5522 331 | 1 | 00331 | Sun Feb 01 00:00:00 1970 PST
5523 333 | 303 | 00333_update3 | Tue Feb 03 00:00:00 1970 PST
5524 334 | 4 | 00334 | Wed Feb 04 00:00:00 1970 PST
5525 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST
5526 337 | 407 | 00337_update7 | Sat Feb 07 00:00:00 1970 PST
5527 338 | 8 | 00338 | Sun Feb 08 00:00:00 1970 PST
5528 339 | 509 | 00339_update9 | Mon Feb 09 00:00:00 1970 PST
5529 340 | 0 | 00340 | Tue Feb 10 00:00:00 1970 PST
5530 341 | 1 | 00341 | Wed Feb 11 00:00:00 1970 PST
5531 343 | 303 | 00343_update3 | Fri Feb 13 00:00:00 1970 PST
5532 344 | 4 | 00344 | Sat Feb 14 00:00:00 1970 PST
5533 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST
5534 347 | 407 | 00347_update7 | Tue Feb 17 00:00:00 1970 PST
5535 348 | 8 | 00348 | Wed Feb 18 00:00:00 1970 PST
5536 349 | 509 | 00349_update9 | Thu Feb 19 00:00:00 1970 PST
5537 350 | 0 | 00350 | Fri Feb 20 00:00:00 1970 PST
5538 351 | 1 | 00351 | Sat Feb 21 00:00:00 1970 PST
5539 353 | 303 | 00353_update3 | Mon Feb 23 00:00:00 1970 PST
5540 354 | 4 | 00354 | Tue Feb 24 00:00:00 1970 PST
5541 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST
5542 357 | 407 | 00357_update7 | Fri Feb 27 00:00:00 1970 PST
5543 358 | 8 | 00358 | Sat Feb 28 00:00:00 1970 PST
5544 359 | 509 | 00359_update9 | Sun Mar 01 00:00:00 1970 PST
5545 360 | 0 | 00360 | Mon Mar 02 00:00:00 1970 PST
5546 361 | 1 | 00361 | Tue Mar 03 00:00:00 1970 PST
5547 363 | 303 | 00363_update3 | Thu Mar 05 00:00:00 1970 PST
5548 364 | 4 | 00364 | Fri Mar 06 00:00:00 1970 PST
5549 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST
5550 367 | 407 | 00367_update7 | Mon Mar 09 00:00:00 1970 PST
5551 368 | 8 | 00368 | Tue Mar 10 00:00:00 1970 PST
5552 369 | 509 | 00369_update9 | Wed Mar 11 00:00:00 1970 PST
5553 370 | 0 | 00370 | Thu Mar 12 00:00:00 1970 PST
5554 371 | 1 | 00371 | Fri Mar 13 00:00:00 1970 PST
5555 373 | 303 | 00373_update3 | Sun Mar 15 00:00:00 1970 PST
5556 374 | 4 | 00374 | Mon Mar 16 00:00:00 1970 PST
5557 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST
5558 377 | 407 | 00377_update7 | Thu Mar 19 00:00:00 1970 PST
5559 378 | 8 | 00378 | Fri Mar 20 00:00:00 1970 PST
5560 379 | 509 | 00379_update9 | Sat Mar 21 00:00:00 1970 PST
5561 380 | 0 | 00380 | Sun Mar 22 00:00:00 1970 PST
5562 381 | 1 | 00381 | Mon Mar 23 00:00:00 1970 PST
5563 383 | 303 | 00383_update3 | Wed Mar 25 00:00:00 1970 PST
5564 384 | 4 | 00384 | Thu Mar 26 00:00:00 1970 PST
5565 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST
5566 387 | 407 | 00387_update7 | Sun Mar 29 00:00:00 1970 PST
5567 388 | 8 | 00388 | Mon Mar 30 00:00:00 1970 PST
5568 389 | 509 | 00389_update9 | Tue Mar 31 00:00:00 1970 PST
5569 390 | 0 | 00390 | Wed Apr 01 00:00:00 1970 PST
5570 391 | 1 | 00391 | Thu Apr 02 00:00:00 1970 PST
5571 393 | 303 | 00393_update3 | Sat Apr 04 00:00:00 1970 PST
5572 394 | 4 | 00394 | Sun Apr 05 00:00:00 1970 PST
5573 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST
5574 397 | 407 | 00397_update7 | Wed Apr 08 00:00:00 1970 PST
5575 398 | 8 | 00398 | Thu Apr 09 00:00:00 1970 PST
5576 399 | 509 | 00399_update9 | Fri Apr 10 00:00:00 1970 PST
5577 400 | 0 | 00400 | Thu Jan 01 00:00:00 1970 PST
5578 401 | 1 | 00401 | Fri Jan 02 00:00:00 1970 PST
5579 403 | 303 | 00403_update3 | Sun Jan 04 00:00:00 1970 PST
5580 404 | 4 | 00404 | Mon Jan 05 00:00:00 1970 PST
5581 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST
5582 407 | 407 | 00407_update7 | Thu Jan 08 00:00:00 1970 PST
5583 408 | 8 | 00408 | Fri Jan 09 00:00:00 1970 PST
5584 409 | 509 | 00409_update9 | Sat Jan 10 00:00:00 1970 PST
5585 410 | 0 | 00410 | Sun Jan 11 00:00:00 1970 PST
5586 411 | 1 | 00411 | Mon Jan 12 00:00:00 1970 PST
5587 413 | 303 | 00413_update3 | Wed Jan 14 00:00:00 1970 PST
5588 414 | 4 | 00414 | Thu Jan 15 00:00:00 1970 PST
5589 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST
5590 417 | 407 | 00417_update7 | Sun Jan 18 00:00:00 1970 PST
5591 418 | 8 | 00418 | Mon Jan 19 00:00:00 1970 PST
5592 419 | 509 | 00419_update9 | Tue Jan 20 00:00:00 1970 PST
5593 420 | 0 | 00420 | Wed Jan 21 00:00:00 1970 PST
5594 421 | 1 | 00421 | Thu Jan 22 00:00:00 1970 PST
5595 423 | 303 | 00423_update3 | Sat Jan 24 00:00:00 1970 PST
5596 424 | 4 | 00424 | Sun Jan 25 00:00:00 1970 PST
5597 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST
5598 427 | 407 | 00427_update7 | Wed Jan 28 00:00:00 1970 PST
5599 428 | 8 | 00428 | Thu Jan 29 00:00:00 1970 PST
5600 429 | 509 | 00429_update9 | Fri Jan 30 00:00:00 1970 PST
5601 430 | 0 | 00430 | Sat Jan 31 00:00:00 1970 PST
5602 431 | 1 | 00431 | Sun Feb 01 00:00:00 1970 PST
5603 433 | 303 | 00433_update3 | Tue Feb 03 00:00:00 1970 PST
5604 434 | 4 | 00434 | Wed Feb 04 00:00:00 1970 PST
5605 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST
5606 437 | 407 | 00437_update7 | Sat Feb 07 00:00:00 1970 PST
5607 438 | 8 | 00438 | Sun Feb 08 00:00:00 1970 PST
5608 439 | 509 | 00439_update9 | Mon Feb 09 00:00:00 1970 PST
5609 440 | 0 | 00440 | Tue Feb 10 00:00:00 1970 PST
5610 441 | 1 | 00441 | Wed Feb 11 00:00:00 1970 PST
5611 443 | 303 | 00443_update3 | Fri Feb 13 00:00:00 1970 PST
5612 444 | 4 | 00444 | Sat Feb 14 00:00:00 1970 PST
5613 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST
5614 447 | 407 | 00447_update7 | Tue Feb 17 00:00:00 1970 PST
5615 448 | 8 | 00448 | Wed Feb 18 00:00:00 1970 PST
5616 449 | 509 | 00449_update9 | Thu Feb 19 00:00:00 1970 PST
5617 450 | 0 | 00450 | Fri Feb 20 00:00:00 1970 PST
5618 451 | 1 | 00451 | Sat Feb 21 00:00:00 1970 PST
5619 453 | 303 | 00453_update3 | Mon Feb 23 00:00:00 1970 PST
5620 454 | 4 | 00454 | Tue Feb 24 00:00:00 1970 PST
5621 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST
5622 457 | 407 | 00457_update7 | Fri Feb 27 00:00:00 1970 PST
5623 458 | 8 | 00458 | Sat Feb 28 00:00:00 1970 PST
5624 459 | 509 | 00459_update9 | Sun Mar 01 00:00:00 1970 PST
5625 460 | 0 | 00460 | Mon Mar 02 00:00:00 1970 PST
5626 461 | 1 | 00461 | Tue Mar 03 00:00:00 1970 PST
5627 463 | 303 | 00463_update3 | Thu Mar 05 00:00:00 1970 PST
5628 464 | 4 | 00464 | Fri Mar 06 00:00:00 1970 PST
5629 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST
5630 467 | 407 | 00467_update7 | Mon Mar 09 00:00:00 1970 PST
5631 468 | 8 | 00468 | Tue Mar 10 00:00:00 1970 PST
5632 469 | 509 | 00469_update9 | Wed Mar 11 00:00:00 1970 PST
5633 470 | 0 | 00470 | Thu Mar 12 00:00:00 1970 PST
5634 471 | 1 | 00471 | Fri Mar 13 00:00:00 1970 PST
5635 473 | 303 | 00473_update3 | Sun Mar 15 00:00:00 1970 PST
5636 474 | 4 | 00474 | Mon Mar 16 00:00:00 1970 PST
5637 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST
5638 477 | 407 | 00477_update7 | Thu Mar 19 00:00:00 1970 PST
5639 478 | 8 | 00478 | Fri Mar 20 00:00:00 1970 PST
5640 479 | 509 | 00479_update9 | Sat Mar 21 00:00:00 1970 PST
5641 480 | 0 | 00480 | Sun Mar 22 00:00:00 1970 PST
5642 481 | 1 | 00481 | Mon Mar 23 00:00:00 1970 PST
5643 483 | 303 | 00483_update3 | Wed Mar 25 00:00:00 1970 PST
5644 484 | 4 | 00484 | Thu Mar 26 00:00:00 1970 PST
5645 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST
5646 487 | 407 | 00487_update7 | Sun Mar 29 00:00:00 1970 PST
5647 488 | 8 | 00488 | Mon Mar 30 00:00:00 1970 PST
5648 489 | 509 | 00489_update9 | Tue Mar 31 00:00:00 1970 PST
5649 490 | 0 | 00490 | Wed Apr 01 00:00:00 1970 PST
5650 491 | 1 | 00491 | Thu Apr 02 00:00:00 1970 PST
5651 493 | 303 | 00493_update3 | Sat Apr 04 00:00:00 1970 PST
5652 494 | 4 | 00494 | Sun Apr 05 00:00:00 1970 PST
5653 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST
5654 497 | 407 | 00497_update7 | Wed Apr 08 00:00:00 1970 PST
5655 498 | 8 | 00498 | Thu Apr 09 00:00:00 1970 PST
5656 499 | 509 | 00499_update9 | Fri Apr 10 00:00:00 1970 PST
5657 500 | 0 | 00500 | Thu Jan 01 00:00:00 1970 PST
5658 501 | 1 | 00501 | Fri Jan 02 00:00:00 1970 PST
5659 503 | 303 | 00503_update3 | Sun Jan 04 00:00:00 1970 PST
5660 504 | 4 | 00504 | Mon Jan 05 00:00:00 1970 PST
5661 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST
5662 507 | 407 | 00507_update7 | Thu Jan 08 00:00:00 1970 PST
5663 508 | 8 | 00508 | Fri Jan 09 00:00:00 1970 PST
5664 509 | 509 | 00509_update9 | Sat Jan 10 00:00:00 1970 PST
5665 510 | 0 | 00510 | Sun Jan 11 00:00:00 1970 PST
5666 511 | 1 | 00511 | Mon Jan 12 00:00:00 1970 PST
5667 513 | 303 | 00513_update3 | Wed Jan 14 00:00:00 1970 PST
5668 514 | 4 | 00514 | Thu Jan 15 00:00:00 1970 PST
5669 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST
5670 517 | 407 | 00517_update7 | Sun Jan 18 00:00:00 1970 PST
5671 518 | 8 | 00518 | Mon Jan 19 00:00:00 1970 PST
5672 519 | 509 | 00519_update9 | Tue Jan 20 00:00:00 1970 PST
5673 520 | 0 | 00520 | Wed Jan 21 00:00:00 1970 PST
5674 521 | 1 | 00521 | Thu Jan 22 00:00:00 1970 PST
5675 523 | 303 | 00523_update3 | Sat Jan 24 00:00:00 1970 PST
5676 524 | 4 | 00524 | Sun Jan 25 00:00:00 1970 PST
5677 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST
5678 527 | 407 | 00527_update7 | Wed Jan 28 00:00:00 1970 PST
5679 528 | 8 | 00528 | Thu Jan 29 00:00:00 1970 PST
5680 529 | 509 | 00529_update9 | Fri Jan 30 00:00:00 1970 PST
5681 530 | 0 | 00530 | Sat Jan 31 00:00:00 1970 PST
5682 531 | 1 | 00531 | Sun Feb 01 00:00:00 1970 PST
5683 533 | 303 | 00533_update3 | Tue Feb 03 00:00:00 1970 PST
5684 534 | 4 | 00534 | Wed Feb 04 00:00:00 1970 PST
5685 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST
5686 537 | 407 | 00537_update7 | Sat Feb 07 00:00:00 1970 PST
5687 538 | 8 | 00538 | Sun Feb 08 00:00:00 1970 PST
5688 539 | 509 | 00539_update9 | Mon Feb 09 00:00:00 1970 PST
5689 540 | 0 | 00540 | Tue Feb 10 00:00:00 1970 PST
5690 541 | 1 | 00541 | Wed Feb 11 00:00:00 1970 PST
5691 543 | 303 | 00543_update3 | Fri Feb 13 00:00:00 1970 PST
5692 544 | 4 | 00544 | Sat Feb 14 00:00:00 1970 PST
5693 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST
5694 547 | 407 | 00547_update7 | Tue Feb 17 00:00:00 1970 PST
5695 548 | 8 | 00548 | Wed Feb 18 00:00:00 1970 PST
5696 549 | 509 | 00549_update9 | Thu Feb 19 00:00:00 1970 PST
5697 550 | 0 | 00550 | Fri Feb 20 00:00:00 1970 PST
5698 551 | 1 | 00551 | Sat Feb 21 00:00:00 1970 PST
5699 553 | 303 | 00553_update3 | Mon Feb 23 00:00:00 1970 PST
5700 554 | 4 | 00554 | Tue Feb 24 00:00:00 1970 PST
5701 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST
5702 557 | 407 | 00557_update7 | Fri Feb 27 00:00:00 1970 PST
5703 558 | 8 | 00558 | Sat Feb 28 00:00:00 1970 PST
5704 559 | 509 | 00559_update9 | Sun Mar 01 00:00:00 1970 PST
5705 560 | 0 | 00560 | Mon Mar 02 00:00:00 1970 PST
5706 561 | 1 | 00561 | Tue Mar 03 00:00:00 1970 PST
5707 563 | 303 | 00563_update3 | Thu Mar 05 00:00:00 1970 PST
5708 564 | 4 | 00564 | Fri Mar 06 00:00:00 1970 PST
5709 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST
5710 567 | 407 | 00567_update7 | Mon Mar 09 00:00:00 1970 PST
5711 568 | 8 | 00568 | Tue Mar 10 00:00:00 1970 PST
5712 569 | 509 | 00569_update9 | Wed Mar 11 00:00:00 1970 PST
5713 570 | 0 | 00570 | Thu Mar 12 00:00:00 1970 PST
5714 571 | 1 | 00571 | Fri Mar 13 00:00:00 1970 PST
5715 573 | 303 | 00573_update3 | Sun Mar 15 00:00:00 1970 PST
5716 574 | 4 | 00574 | Mon Mar 16 00:00:00 1970 PST
5717 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST
5718 577 | 407 | 00577_update7 | Thu Mar 19 00:00:00 1970 PST
5719 578 | 8 | 00578 | Fri Mar 20 00:00:00 1970 PST
5720 579 | 509 | 00579_update9 | Sat Mar 21 00:00:00 1970 PST
5721 580 | 0 | 00580 | Sun Mar 22 00:00:00 1970 PST
5722 581 | 1 | 00581 | Mon Mar 23 00:00:00 1970 PST
5723 583 | 303 | 00583_update3 | Wed Mar 25 00:00:00 1970 PST
5724 584 | 4 | 00584 | Thu Mar 26 00:00:00 1970 PST
5725 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST
5726 587 | 407 | 00587_update7 | Sun Mar 29 00:00:00 1970 PST
5727 588 | 8 | 00588 | Mon Mar 30 00:00:00 1970 PST
5728 589 | 509 | 00589_update9 | Tue Mar 31 00:00:00 1970 PST
5729 590 | 0 | 00590 | Wed Apr 01 00:00:00 1970 PST
5730 591 | 1 | 00591 | Thu Apr 02 00:00:00 1970 PST
5731 593 | 303 | 00593_update3 | Sat Apr 04 00:00:00 1970 PST
5732 594 | 4 | 00594 | Sun Apr 05 00:00:00 1970 PST
5733 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST
5734 597 | 407 | 00597_update7 | Wed Apr 08 00:00:00 1970 PST
5735 598 | 8 | 00598 | Thu Apr 09 00:00:00 1970 PST
5736 599 | 509 | 00599_update9 | Fri Apr 10 00:00:00 1970 PST
5737 600 | 0 | 00600 | Thu Jan 01 00:00:00 1970 PST
5738 601 | 1 | 00601 | Fri Jan 02 00:00:00 1970 PST
5739 603 | 303 | 00603_update3 | Sun Jan 04 00:00:00 1970 PST
5740 604 | 4 | 00604 | Mon Jan 05 00:00:00 1970 PST
5741 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST
5742 607 | 407 | 00607_update7 | Thu Jan 08 00:00:00 1970 PST
5743 608 | 8 | 00608 | Fri Jan 09 00:00:00 1970 PST
5744 609 | 509 | 00609_update9 | Sat Jan 10 00:00:00 1970 PST
5745 610 | 0 | 00610 | Sun Jan 11 00:00:00 1970 PST
5746 611 | 1 | 00611 | Mon Jan 12 00:00:00 1970 PST
5747 613 | 303 | 00613_update3 | Wed Jan 14 00:00:00 1970 PST
5748 614 | 4 | 00614 | Thu Jan 15 00:00:00 1970 PST
5749 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST
5750 617 | 407 | 00617_update7 | Sun Jan 18 00:00:00 1970 PST
5751 618 | 8 | 00618 | Mon Jan 19 00:00:00 1970 PST
5752 619 | 509 | 00619_update9 | Tue Jan 20 00:00:00 1970 PST
5753 620 | 0 | 00620 | Wed Jan 21 00:00:00 1970 PST
5754 621 | 1 | 00621 | Thu Jan 22 00:00:00 1970 PST
5755 623 | 303 | 00623_update3 | Sat Jan 24 00:00:00 1970 PST
5756 624 | 4 | 00624 | Sun Jan 25 00:00:00 1970 PST
5757 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST
5758 627 | 407 | 00627_update7 | Wed Jan 28 00:00:00 1970 PST
5759 628 | 8 | 00628 | Thu Jan 29 00:00:00 1970 PST
5760 629 | 509 | 00629_update9 | Fri Jan 30 00:00:00 1970 PST
5761 630 | 0 | 00630 | Sat Jan 31 00:00:00 1970 PST
5762 631 | 1 | 00631 | Sun Feb 01 00:00:00 1970 PST
5763 633 | 303 | 00633_update3 | Tue Feb 03 00:00:00 1970 PST
5764 634 | 4 | 00634 | Wed Feb 04 00:00:00 1970 PST
5765 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST
5766 637 | 407 | 00637_update7 | Sat Feb 07 00:00:00 1970 PST
5767 638 | 8 | 00638 | Sun Feb 08 00:00:00 1970 PST
5768 639 | 509 | 00639_update9 | Mon Feb 09 00:00:00 1970 PST
5769 640 | 0 | 00640 | Tue Feb 10 00:00:00 1970 PST
5770 641 | 1 | 00641 | Wed Feb 11 00:00:00 1970 PST
5771 643 | 303 | 00643_update3 | Fri Feb 13 00:00:00 1970 PST
5772 644 | 4 | 00644 | Sat Feb 14 00:00:00 1970 PST
5773 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST
5774 647 | 407 | 00647_update7 | Tue Feb 17 00:00:00 1970 PST
5775 648 | 8 | 00648 | Wed Feb 18 00:00:00 1970 PST
5776 649 | 509 | 00649_update9 | Thu Feb 19 00:00:00 1970 PST
5777 650 | 0 | 00650 | Fri Feb 20 00:00:00 1970 PST
5778 651 | 1 | 00651 | Sat Feb 21 00:00:00 1970 PST
5779 653 | 303 | 00653_update3 | Mon Feb 23 00:00:00 1970 PST
5780 654 | 4 | 00654 | Tue Feb 24 00:00:00 1970 PST
5781 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST
5782 657 | 407 | 00657_update7 | Fri Feb 27 00:00:00 1970 PST
5783 658 | 8 | 00658 | Sat Feb 28 00:00:00 1970 PST
5784 659 | 509 | 00659_update9 | Sun Mar 01 00:00:00 1970 PST
5785 660 | 0 | 00660 | Mon Mar 02 00:00:00 1970 PST
5786 661 | 1 | 00661 | Tue Mar 03 00:00:00 1970 PST
5787 663 | 303 | 00663_update3 | Thu Mar 05 00:00:00 1970 PST
5788 664 | 4 | 00664 | Fri Mar 06 00:00:00 1970 PST
5789 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST
5790 667 | 407 | 00667_update7 | Mon Mar 09 00:00:00 1970 PST
5791 668 | 8 | 00668 | Tue Mar 10 00:00:00 1970 PST
5792 669 | 509 | 00669_update9 | Wed Mar 11 00:00:00 1970 PST
5793 670 | 0 | 00670 | Thu Mar 12 00:00:00 1970 PST
5794 671 | 1 | 00671 | Fri Mar 13 00:00:00 1970 PST
5795 673 | 303 | 00673_update3 | Sun Mar 15 00:00:00 1970 PST
5796 674 | 4 | 00674 | Mon Mar 16 00:00:00 1970 PST
5797 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST
5798 677 | 407 | 00677_update7 | Thu Mar 19 00:00:00 1970 PST
5799 678 | 8 | 00678 | Fri Mar 20 00:00:00 1970 PST
5800 679 | 509 | 00679_update9 | Sat Mar 21 00:00:00 1970 PST
5801 680 | 0 | 00680 | Sun Mar 22 00:00:00 1970 PST
5802 681 | 1 | 00681 | Mon Mar 23 00:00:00 1970 PST
5803 683 | 303 | 00683_update3 | Wed Mar 25 00:00:00 1970 PST
5804 684 | 4 | 00684 | Thu Mar 26 00:00:00 1970 PST
5805 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST
5806 687 | 407 | 00687_update7 | Sun Mar 29 00:00:00 1970 PST
5807 688 | 8 | 00688 | Mon Mar 30 00:00:00 1970 PST
5808 689 | 509 | 00689_update9 | Tue Mar 31 00:00:00 1970 PST
5809 690 | 0 | 00690 | Wed Apr 01 00:00:00 1970 PST
5810 691 | 1 | 00691 | Thu Apr 02 00:00:00 1970 PST
5811 693 | 303 | 00693_update3 | Sat Apr 04 00:00:00 1970 PST
5812 694 | 4 | 00694 | Sun Apr 05 00:00:00 1970 PST
5813 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST
5814 697 | 407 | 00697_update7 | Wed Apr 08 00:00:00 1970 PST
5815 698 | 8 | 00698 | Thu Apr 09 00:00:00 1970 PST
5816 699 | 509 | 00699_update9 | Fri Apr 10 00:00:00 1970 PST
5817 700 | 0 | 00700 | Thu Jan 01 00:00:00 1970 PST
5818 701 | 1 | 00701 | Fri Jan 02 00:00:00 1970 PST
5819 703 | 303 | 00703_update3 | Sun Jan 04 00:00:00 1970 PST
5820 704 | 4 | 00704 | Mon Jan 05 00:00:00 1970 PST
5821 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST
5822 707 | 407 | 00707_update7 | Thu Jan 08 00:00:00 1970 PST
5823 708 | 8 | 00708 | Fri Jan 09 00:00:00 1970 PST
5824 709 | 509 | 00709_update9 | Sat Jan 10 00:00:00 1970 PST
5825 710 | 0 | 00710 | Sun Jan 11 00:00:00 1970 PST
5826 711 | 1 | 00711 | Mon Jan 12 00:00:00 1970 PST
5827 713 | 303 | 00713_update3 | Wed Jan 14 00:00:00 1970 PST
5828 714 | 4 | 00714 | Thu Jan 15 00:00:00 1970 PST
5829 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST
5830 717 | 407 | 00717_update7 | Sun Jan 18 00:00:00 1970 PST
5831 718 | 8 | 00718 | Mon Jan 19 00:00:00 1970 PST
5832 719 | 509 | 00719_update9 | Tue Jan 20 00:00:00 1970 PST
5833 720 | 0 | 00720 | Wed Jan 21 00:00:00 1970 PST
5834 721 | 1 | 00721 | Thu Jan 22 00:00:00 1970 PST
5835 723 | 303 | 00723_update3 | Sat Jan 24 00:00:00 1970 PST
5836 724 | 4 | 00724 | Sun Jan 25 00:00:00 1970 PST
5837 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST
5838 727 | 407 | 00727_update7 | Wed Jan 28 00:00:00 1970 PST
5839 728 | 8 | 00728 | Thu Jan 29 00:00:00 1970 PST
5840 729 | 509 | 00729_update9 | Fri Jan 30 00:00:00 1970 PST
5841 730 | 0 | 00730 | Sat Jan 31 00:00:00 1970 PST
5842 731 | 1 | 00731 | Sun Feb 01 00:00:00 1970 PST
5843 733 | 303 | 00733_update3 | Tue Feb 03 00:00:00 1970 PST
5844 734 | 4 | 00734 | Wed Feb 04 00:00:00 1970 PST
5845 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST
5846 737 | 407 | 00737_update7 | Sat Feb 07 00:00:00 1970 PST
5847 738 | 8 | 00738 | Sun Feb 08 00:00:00 1970 PST
5848 739 | 509 | 00739_update9 | Mon Feb 09 00:00:00 1970 PST
5849 740 | 0 | 00740 | Tue Feb 10 00:00:00 1970 PST
5850 741 | 1 | 00741 | Wed Feb 11 00:00:00 1970 PST
5851 743 | 303 | 00743_update3 | Fri Feb 13 00:00:00 1970 PST
5852 744 | 4 | 00744 | Sat Feb 14 00:00:00 1970 PST
5853 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST
5854 747 | 407 | 00747_update7 | Tue Feb 17 00:00:00 1970 PST
5855 748 | 8 | 00748 | Wed Feb 18 00:00:00 1970 PST
5856 749 | 509 | 00749_update9 | Thu Feb 19 00:00:00 1970 PST
5857 750 | 0 | 00750 | Fri Feb 20 00:00:00 1970 PST
5858 751 | 1 | 00751 | Sat Feb 21 00:00:00 1970 PST
5859 753 | 303 | 00753_update3 | Mon Feb 23 00:00:00 1970 PST
5860 754 | 4 | 00754 | Tue Feb 24 00:00:00 1970 PST
5861 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST
5862 757 | 407 | 00757_update7 | Fri Feb 27 00:00:00 1970 PST
5863 758 | 8 | 00758 | Sat Feb 28 00:00:00 1970 PST
5864 759 | 509 | 00759_update9 | Sun Mar 01 00:00:00 1970 PST
5865 760 | 0 | 00760 | Mon Mar 02 00:00:00 1970 PST
5866 761 | 1 | 00761 | Tue Mar 03 00:00:00 1970 PST
5867 763 | 303 | 00763_update3 | Thu Mar 05 00:00:00 1970 PST
5868 764 | 4 | 00764 | Fri Mar 06 00:00:00 1970 PST
5869 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST
5870 767 | 407 | 00767_update7 | Mon Mar 09 00:00:00 1970 PST
5871 768 | 8 | 00768 | Tue Mar 10 00:00:00 1970 PST
5872 769 | 509 | 00769_update9 | Wed Mar 11 00:00:00 1970 PST
5873 770 | 0 | 00770 | Thu Mar 12 00:00:00 1970 PST
5874 771 | 1 | 00771 | Fri Mar 13 00:00:00 1970 PST
5875 773 | 303 | 00773_update3 | Sun Mar 15 00:00:00 1970 PST
5876 774 | 4 | 00774 | Mon Mar 16 00:00:00 1970 PST
5877 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST
5878 777 | 407 | 00777_update7 | Thu Mar 19 00:00:00 1970 PST
5879 778 | 8 | 00778 | Fri Mar 20 00:00:00 1970 PST
5880 779 | 509 | 00779_update9 | Sat Mar 21 00:00:00 1970 PST
5881 780 | 0 | 00780 | Sun Mar 22 00:00:00 1970 PST
5882 781 | 1 | 00781 | Mon Mar 23 00:00:00 1970 PST
5883 783 | 303 | 00783_update3 | Wed Mar 25 00:00:00 1970 PST
5884 784 | 4 | 00784 | Thu Mar 26 00:00:00 1970 PST
5885 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST
5886 787 | 407 | 00787_update7 | Sun Mar 29 00:00:00 1970 PST
5887 788 | 8 | 00788 | Mon Mar 30 00:00:00 1970 PST
5888 789 | 509 | 00789_update9 | Tue Mar 31 00:00:00 1970 PST
5889 790 | 0 | 00790 | Wed Apr 01 00:00:00 1970 PST
5890 791 | 1 | 00791 | Thu Apr 02 00:00:00 1970 PST
5891 793 | 303 | 00793_update3 | Sat Apr 04 00:00:00 1970 PST
5892 794 | 4 | 00794 | Sun Apr 05 00:00:00 1970 PST
5893 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST
5894 797 | 407 | 00797_update7 | Wed Apr 08 00:00:00 1970 PST
5895 798 | 8 | 00798 | Thu Apr 09 00:00:00 1970 PST
5896 799 | 509 | 00799_update9 | Fri Apr 10 00:00:00 1970 PST
5897 800 | 0 | 00800 | Thu Jan 01 00:00:00 1970 PST
5898 801 | 1 | 00801 | Fri Jan 02 00:00:00 1970 PST
5899 803 | 303 | 00803_update3 | Sun Jan 04 00:00:00 1970 PST
5900 804 | 4 | 00804 | Mon Jan 05 00:00:00 1970 PST
5901 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST
5902 807 | 407 | 00807_update7 | Thu Jan 08 00:00:00 1970 PST
5903 808 | 8 | 00808 | Fri Jan 09 00:00:00 1970 PST
5904 809 | 509 | 00809_update9 | Sat Jan 10 00:00:00 1970 PST
5905 810 | 0 | 00810 | Sun Jan 11 00:00:00 1970 PST
5906 811 | 1 | 00811 | Mon Jan 12 00:00:00 1970 PST
5907 813 | 303 | 00813_update3 | Wed Jan 14 00:00:00 1970 PST
5908 814 | 4 | 00814 | Thu Jan 15 00:00:00 1970 PST
5909 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST
5910 817 | 407 | 00817_update7 | Sun Jan 18 00:00:00 1970 PST
5911 818 | 8 | 00818 | Mon Jan 19 00:00:00 1970 PST
5912 819 | 509 | 00819_update9 | Tue Jan 20 00:00:00 1970 PST
5913 820 | 0 | 00820 | Wed Jan 21 00:00:00 1970 PST
5914 821 | 1 | 00821 | Thu Jan 22 00:00:00 1970 PST
5915 823 | 303 | 00823_update3 | Sat Jan 24 00:00:00 1970 PST
5916 824 | 4 | 00824 | Sun Jan 25 00:00:00 1970 PST
5917 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST
5918 827 | 407 | 00827_update7 | Wed Jan 28 00:00:00 1970 PST
5919 828 | 8 | 00828 | Thu Jan 29 00:00:00 1970 PST
5920 829 | 509 | 00829_update9 | Fri Jan 30 00:00:00 1970 PST
5921 830 | 0 | 00830 | Sat Jan 31 00:00:00 1970 PST
5922 831 | 1 | 00831 | Sun Feb 01 00:00:00 1970 PST
5923 833 | 303 | 00833_update3 | Tue Feb 03 00:00:00 1970 PST
5924 834 | 4 | 00834 | Wed Feb 04 00:00:00 1970 PST
5925 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST
5926 837 | 407 | 00837_update7 | Sat Feb 07 00:00:00 1970 PST
5927 838 | 8 | 00838 | Sun Feb 08 00:00:00 1970 PST
5928 839 | 509 | 00839_update9 | Mon Feb 09 00:00:00 1970 PST
5929 840 | 0 | 00840 | Tue Feb 10 00:00:00 1970 PST
5930 841 | 1 | 00841 | Wed Feb 11 00:00:00 1970 PST
5931 843 | 303 | 00843_update3 | Fri Feb 13 00:00:00 1970 PST
5932 844 | 4 | 00844 | Sat Feb 14 00:00:00 1970 PST
5933 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST
5934 847 | 407 | 00847_update7 | Tue Feb 17 00:00:00 1970 PST
5935 848 | 8 | 00848 | Wed Feb 18 00:00:00 1970 PST
5936 849 | 509 | 00849_update9 | Thu Feb 19 00:00:00 1970 PST
5937 850 | 0 | 00850 | Fri Feb 20 00:00:00 1970 PST
5938 851 | 1 | 00851 | Sat Feb 21 00:00:00 1970 PST
5939 853 | 303 | 00853_update3 | Mon Feb 23 00:00:00 1970 PST
5940 854 | 4 | 00854 | Tue Feb 24 00:00:00 1970 PST
5941 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST
5942 857 | 407 | 00857_update7 | Fri Feb 27 00:00:00 1970 PST
5943 858 | 8 | 00858 | Sat Feb 28 00:00:00 1970 PST
5944 859 | 509 | 00859_update9 | Sun Mar 01 00:00:00 1970 PST
5945 860 | 0 | 00860 | Mon Mar 02 00:00:00 1970 PST
5946 861 | 1 | 00861 | Tue Mar 03 00:00:00 1970 PST
5947 863 | 303 | 00863_update3 | Thu Mar 05 00:00:00 1970 PST
5948 864 | 4 | 00864 | Fri Mar 06 00:00:00 1970 PST
5949 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST
5950 867 | 407 | 00867_update7 | Mon Mar 09 00:00:00 1970 PST
5951 868 | 8 | 00868 | Tue Mar 10 00:00:00 1970 PST
5952 869 | 509 | 00869_update9 | Wed Mar 11 00:00:00 1970 PST
5953 870 | 0 | 00870 | Thu Mar 12 00:00:00 1970 PST
5954 871 | 1 | 00871 | Fri Mar 13 00:00:00 1970 PST
5955 873 | 303 | 00873_update3 | Sun Mar 15 00:00:00 1970 PST
5956 874 | 4 | 00874 | Mon Mar 16 00:00:00 1970 PST
5957 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST
5958 877 | 407 | 00877_update7 | Thu Mar 19 00:00:00 1970 PST
5959 878 | 8 | 00878 | Fri Mar 20 00:00:00 1970 PST
5960 879 | 509 | 00879_update9 | Sat Mar 21 00:00:00 1970 PST
5961 880 | 0 | 00880 | Sun Mar 22 00:00:00 1970 PST
5962 881 | 1 | 00881 | Mon Mar 23 00:00:00 1970 PST
5963 883 | 303 | 00883_update3 | Wed Mar 25 00:00:00 1970 PST
5964 884 | 4 | 00884 | Thu Mar 26 00:00:00 1970 PST
5965 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST
5966 887 | 407 | 00887_update7 | Sun Mar 29 00:00:00 1970 PST
5967 888 | 8 | 00888 | Mon Mar 30 00:00:00 1970 PST
5968 889 | 509 | 00889_update9 | Tue Mar 31 00:00:00 1970 PST
5969 890 | 0 | 00890 | Wed Apr 01 00:00:00 1970 PST
5970 891 | 1 | 00891 | Thu Apr 02 00:00:00 1970 PST
5971 893 | 303 | 00893_update3 | Sat Apr 04 00:00:00 1970 PST
5972 894 | 4 | 00894 | Sun Apr 05 00:00:00 1970 PST
5973 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST
5974 897 | 407 | 00897_update7 | Wed Apr 08 00:00:00 1970 PST
5975 898 | 8 | 00898 | Thu Apr 09 00:00:00 1970 PST
5976 899 | 509 | 00899_update9 | Fri Apr 10 00:00:00 1970 PST
5977 900 | 0 | 00900 | Thu Jan 01 00:00:00 1970 PST
5978 901 | 1 | 00901 | Fri Jan 02 00:00:00 1970 PST
5979 903 | 303 | 00903_update3 | Sun Jan 04 00:00:00 1970 PST
5980 904 | 4 | 00904 | Mon Jan 05 00:00:00 1970 PST
5981 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST
5982 907 | 407 | 00907_update7 | Thu Jan 08 00:00:00 1970 PST
5983 908 | 8 | 00908 | Fri Jan 09 00:00:00 1970 PST
5984 909 | 509 | 00909_update9 | Sat Jan 10 00:00:00 1970 PST
5985 910 | 0 | 00910 | Sun Jan 11 00:00:00 1970 PST
5986 911 | 1 | 00911 | Mon Jan 12 00:00:00 1970 PST
5987 913 | 303 | 00913_update3 | Wed Jan 14 00:00:00 1970 PST
5988 914 | 4 | 00914 | Thu Jan 15 00:00:00 1970 PST
5989 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST
5990 917 | 407 | 00917_update7 | Sun Jan 18 00:00:00 1970 PST
5991 918 | 8 | 00918 | Mon Jan 19 00:00:00 1970 PST
5992 919 | 509 | 00919_update9 | Tue Jan 20 00:00:00 1970 PST
5993 920 | 0 | 00920 | Wed Jan 21 00:00:00 1970 PST
5994 921 | 1 | 00921 | Thu Jan 22 00:00:00 1970 PST
5995 923 | 303 | 00923_update3 | Sat Jan 24 00:00:00 1970 PST
5996 924 | 4 | 00924 | Sun Jan 25 00:00:00 1970 PST
5997 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST
5998 927 | 407 | 00927_update7 | Wed Jan 28 00:00:00 1970 PST
5999 928 | 8 | 00928 | Thu Jan 29 00:00:00 1970 PST
6000 929 | 509 | 00929_update9 | Fri Jan 30 00:00:00 1970 PST
6001 930 | 0 | 00930 | Sat Jan 31 00:00:00 1970 PST
6002 931 | 1 | 00931 | Sun Feb 01 00:00:00 1970 PST
6003 933 | 303 | 00933_update3 | Tue Feb 03 00:00:00 1970 PST
6004 934 | 4 | 00934 | Wed Feb 04 00:00:00 1970 PST
6005 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST
6006 937 | 407 | 00937_update7 | Sat Feb 07 00:00:00 1970 PST
6007 938 | 8 | 00938 | Sun Feb 08 00:00:00 1970 PST
6008 939 | 509 | 00939_update9 | Mon Feb 09 00:00:00 1970 PST
6009 940 | 0 | 00940 | Tue Feb 10 00:00:00 1970 PST
6010 941 | 1 | 00941 | Wed Feb 11 00:00:00 1970 PST
6011 943 | 303 | 00943_update3 | Fri Feb 13 00:00:00 1970 PST
6012 944 | 4 | 00944 | Sat Feb 14 00:00:00 1970 PST
6013 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST
6014 947 | 407 | 00947_update7 | Tue Feb 17 00:00:00 1970 PST
6015 948 | 8 | 00948 | Wed Feb 18 00:00:00 1970 PST
6016 949 | 509 | 00949_update9 | Thu Feb 19 00:00:00 1970 PST
6017 950 | 0 | 00950 | Fri Feb 20 00:00:00 1970 PST
6018 951 | 1 | 00951 | Sat Feb 21 00:00:00 1970 PST
6019 953 | 303 | 00953_update3 | Mon Feb 23 00:00:00 1970 PST
6020 954 | 4 | 00954 | Tue Feb 24 00:00:00 1970 PST
6021 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST
6022 957 | 407 | 00957_update7 | Fri Feb 27 00:00:00 1970 PST
6023 958 | 8 | 00958 | Sat Feb 28 00:00:00 1970 PST
6024 959 | 509 | 00959_update9 | Sun Mar 01 00:00:00 1970 PST
6025 960 | 0 | 00960 | Mon Mar 02 00:00:00 1970 PST
6026 961 | 1 | 00961 | Tue Mar 03 00:00:00 1970 PST
6027 963 | 303 | 00963_update3 | Thu Mar 05 00:00:00 1970 PST
6028 964 | 4 | 00964 | Fri Mar 06 00:00:00 1970 PST
6029 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST
6030 967 | 407 | 00967_update7 | Mon Mar 09 00:00:00 1970 PST
6031 968 | 8 | 00968 | Tue Mar 10 00:00:00 1970 PST
6032 969 | 509 | 00969_update9 | Wed Mar 11 00:00:00 1970 PST
6033 970 | 0 | 00970 | Thu Mar 12 00:00:00 1970 PST
6034 971 | 1 | 00971 | Fri Mar 13 00:00:00 1970 PST
6035 973 | 303 | 00973_update3 | Sun Mar 15 00:00:00 1970 PST
6036 974 | 4 | 00974 | Mon Mar 16 00:00:00 1970 PST
6037 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST
6038 977 | 407 | 00977_update7 | Thu Mar 19 00:00:00 1970 PST
6039 978 | 8 | 00978 | Fri Mar 20 00:00:00 1970 PST
6040 979 | 509 | 00979_update9 | Sat Mar 21 00:00:00 1970 PST
6041 980 | 0 | 00980 | Sun Mar 22 00:00:00 1970 PST
6042 981 | 1 | 00981 | Mon Mar 23 00:00:00 1970 PST
6043 983 | 303 | 00983_update3 | Wed Mar 25 00:00:00 1970 PST
6044 984 | 4 | 00984 | Thu Mar 26 00:00:00 1970 PST
6045 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST
6046 987 | 407 | 00987_update7 | Sun Mar 29 00:00:00 1970 PST
6047 988 | 8 | 00988 | Mon Mar 30 00:00:00 1970 PST
6048 989 | 509 | 00989_update9 | Tue Mar 31 00:00:00 1970 PST
6049 990 | 0 | 00990 | Wed Apr 01 00:00:00 1970 PST
6050 991 | 1 | 00991 | Thu Apr 02 00:00:00 1970 PST
6051 993 | 303 | 00993_update3 | Sat Apr 04 00:00:00 1970 PST
6052 994 | 4 | 00994 | Sun Apr 05 00:00:00 1970 PST
6053 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST
6054 997 | 407 | 00997_update7 | Wed Apr 08 00:00:00 1970 PST
6055 998 | 8 | 00998 | Thu Apr 09 00:00:00 1970 PST
6056 999 | 509 | 00999_update9 | Fri Apr 10 00:00:00 1970 PST
6057 1000 | 0 | 01000 | Thu Jan 01 00:00:00 1970 PST
6058 1001 | 101 | 0000100001 |
6059 1003 | 403 | 0000300003_update3 |
6060 1004 | 104 | 0000400004 |
6061 1006 | 106 | 0000600006 |
6062 1007 | 507 | 0000700007_update7 |
6063 1008 | 108 | 0000800008 |
6064 1009 | 609 | 0000900009_update9 |
6065 1010 | 100 | 0001000010 |
6066 1011 | 101 | 0001100011 |
6067 1013 | 403 | 0001300013_update3 |
6068 1014 | 104 | 0001400014 |
6069 1016 | 106 | 0001600016 |
6070 1017 | 507 | 0001700017_update7 |
6071 1018 | 108 | 0001800018 |
6072 1019 | 609 | 0001900019_update9 |
6073 1020 | 100 | 0002000020 |
6075 1103 | 503 | ccc_update3 |
6079 EXPLAIN (verbose, costs off)
6080 INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo') RETURNING tableoid::regclass;
6082 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6083 Insert on public.ft2
6084 Output: (ft2.tableoid)::regclass
6085 Remote SQL: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
6088 Output: 1200, 999, NULL::integer, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2 '::character(10), NULL::user_enum
6091 INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo') RETURNING tableoid::regclass;
6097 EXPLAIN (verbose, costs off)
6098 UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200 RETURNING tableoid::regclass; -- can be pushed down
6100 ------------------------------------------------------------------------------------
6101 Update on public.ft2
6102 Output: (tableoid)::regclass
6103 -> Foreign Update on public.ft2
6104 Remote SQL: UPDATE "S 1"."T 1" SET c3 = 'bar'::text WHERE (("C 1" = 1200))
6107 UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200 RETURNING tableoid::regclass;
6113 EXPLAIN (verbose, costs off)
6114 DELETE FROM ft2 WHERE c1 = 1200 RETURNING tableoid::regclass; -- can be pushed down
6116 --------------------------------------------------------------------
6117 Delete on public.ft2
6118 Output: (tableoid)::regclass
6119 -> Foreign Delete on public.ft2
6120 Remote SQL: DELETE FROM "S 1"."T 1" WHERE (("C 1" = 1200))
6123 DELETE FROM ft2 WHERE c1 = 1200 RETURNING tableoid::regclass;
6129 -- Test UPDATE/DELETE with RETURNING on a three-table join
6130 INSERT INTO ft2 (c1,c2,c3)
6131 SELECT id, id - 1200, to_char(id, 'FM00000') FROM generate_series(1201, 1300) id;
6132 EXPLAIN (verbose, costs off)
6133 UPDATE ft2 SET c3 = 'foo'
6134 FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
6135 WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
6136 RETURNING ft2, ft2.*, ft4, ft4.*; -- can be pushed down
6138 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6139 Update on public.ft2
6140 Output: ft2.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.*, ft4.c1, ft4.c2, ft4.c3
6142 Remote SQL: UPDATE "S 1"."T 1" r1 SET c3 = 'foo'::text FROM ("S 1"."T 3" r2 INNER JOIN "S 1"."T 4" r3 ON (TRUE)) WHERE ((r2.c1 = r3.c1)) AND ((r1.c2 = r2.c1)) AND ((r1."C 1" > 1200)) RETURNING r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2.c1, r2.c2, r2.c3) END, r2.c1, r2.c2, r2.c3
6145 UPDATE ft2 SET c3 = 'foo'
6146 FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
6147 WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
6148 RETURNING ft2, ft2.*, ft4, ft4.*;
6149 ft2 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | ft4 | c1 | c2 | c3
6150 --------------------------------+------+----+-----+----+----+----+------------+----+----------------+----+----+--------
6151 (1206,6,foo,,,,"ft2 ",) | 1206 | 6 | foo | | | | ft2 | | (6,7,AAA006) | 6 | 7 | AAA006
6152 (1212,12,foo,,,,"ft2 ",) | 1212 | 12 | foo | | | | ft2 | | (12,13,AAA012) | 12 | 13 | AAA012
6153 (1218,18,foo,,,,"ft2 ",) | 1218 | 18 | foo | | | | ft2 | | (18,19,AAA018) | 18 | 19 | AAA018
6154 (1224,24,foo,,,,"ft2 ",) | 1224 | 24 | foo | | | | ft2 | | (24,25,AAA024) | 24 | 25 | AAA024
6155 (1230,30,foo,,,,"ft2 ",) | 1230 | 30 | foo | | | | ft2 | | (30,31,AAA030) | 30 | 31 | AAA030
6156 (1236,36,foo,,,,"ft2 ",) | 1236 | 36 | foo | | | | ft2 | | (36,37,AAA036) | 36 | 37 | AAA036
6157 (1242,42,foo,,,,"ft2 ",) | 1242 | 42 | foo | | | | ft2 | | (42,43,AAA042) | 42 | 43 | AAA042
6158 (1248,48,foo,,,,"ft2 ",) | 1248 | 48 | foo | | | | ft2 | | (48,49,AAA048) | 48 | 49 | AAA048
6159 (1254,54,foo,,,,"ft2 ",) | 1254 | 54 | foo | | | | ft2 | | (54,55,AAA054) | 54 | 55 | AAA054
6160 (1260,60,foo,,,,"ft2 ",) | 1260 | 60 | foo | | | | ft2 | | (60,61,AAA060) | 60 | 61 | AAA060
6161 (1266,66,foo,,,,"ft2 ",) | 1266 | 66 | foo | | | | ft2 | | (66,67,AAA066) | 66 | 67 | AAA066
6162 (1272,72,foo,,,,"ft2 ",) | 1272 | 72 | foo | | | | ft2 | | (72,73,AAA072) | 72 | 73 | AAA072
6163 (1278,78,foo,,,,"ft2 ",) | 1278 | 78 | foo | | | | ft2 | | (78,79,AAA078) | 78 | 79 | AAA078
6164 (1284,84,foo,,,,"ft2 ",) | 1284 | 84 | foo | | | | ft2 | | (84,85,AAA084) | 84 | 85 | AAA084
6165 (1290,90,foo,,,,"ft2 ",) | 1290 | 90 | foo | | | | ft2 | | (90,91,AAA090) | 90 | 91 | AAA090
6166 (1296,96,foo,,,,"ft2 ",) | 1296 | 96 | foo | | | | ft2 | | (96,97,AAA096) | 96 | 97 | AAA096
6169 EXPLAIN (verbose, costs off)
6171 USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1)
6172 WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1
6173 RETURNING 100; -- can be pushed down
6175 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6176 Delete on public.ft2
6179 Remote SQL: DELETE FROM "S 1"."T 1" r1 USING ("S 1"."T 3" r2 LEFT JOIN "S 1"."T 4" r3 ON (((r2.c1 = r3.c1)))) WHERE ((r1.c2 = r2.c1)) AND ((r1."C 1" > 1200)) AND (((r1."C 1" % 10) = 0))
6183 USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1)
6184 WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1
6200 DELETE FROM ft2 WHERE ft2.c1 > 1200;
6201 -- Test UPDATE with a MULTIEXPR sub-select
6202 -- (maybe someday this'll be remotely executable, but not today)
6203 EXPLAIN (verbose, costs off)
6204 UPDATE ft2 AS target SET (c2, c7) = (
6207 WHERE target.c1 = src.c1
6210 -----------------------------------------------------------------------------------------------------------------------
6211 Update on public.ft2 target
6212 Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c7 = $3 WHERE ctid = $1
6213 -> Foreign Scan on public.ft2 target
6214 Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), target.ctid, target.*
6215 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 1100)) FOR UPDATE
6217 -> Foreign Scan on public.ft2 src
6218 Output: (src.c2 * 10), src.c7
6219 Remote SQL: SELECT c2, c7 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
6222 UPDATE ft2 AS target SET (c2, c7) = (
6225 WHERE target.c1 = src.c1
6227 UPDATE ft2 AS target SET (c2) = (
6230 WHERE target.c1 = src.c1
6232 -- Test UPDATE involving a join that can be pushed down,
6233 -- but a SET clause that can't be
6234 EXPLAIN (VERBOSE, COSTS OFF)
6235 UPDATE ft2 d SET c2 = CASE WHEN random() >= 0 THEN d.c2 ELSE 0 END
6236 FROM ft2 AS t WHERE d.c1 = t.c1 AND d.c1 > 1000;
6238 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6239 Update on public.ft2 d
6240 Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2 WHERE ctid = $1
6242 Output: CASE WHEN (random() >= '0'::double precision) THEN d.c2 ELSE 0 END, d.ctid, d.*, t.*
6243 Relations: (public.ft2 d) INNER JOIN (public.ft2 t)
6244 Remote SQL: SELECT r1.c2, r1.ctid, CASE WHEN (r1.*)::text IS NOT NULL THEN ROW(r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8) END, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")) AND ((r1."C 1" > 1000)))) FOR UPDATE OF r1
6246 Output: d.c2, d.ctid, d.*, t.*
6247 Hash Cond: (d.c1 = t.c1)
6248 -> Foreign Scan on public.ft2 d
6249 Output: d.c2, d.ctid, d.*, d.c1
6250 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 1000)) ORDER BY "C 1" ASC NULLS LAST FOR UPDATE
6253 -> Foreign Scan on public.ft2 t
6255 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
6258 UPDATE ft2 d SET c2 = CASE WHEN random() >= 0 THEN d.c2 ELSE 0 END
6259 FROM ft2 AS t WHERE d.c1 = t.c1 AND d.c1 > 1000;
6260 -- Test UPDATE/DELETE with WHERE or JOIN/ON conditions containing
6261 -- user-defined operators/functions
6262 ALTER SERVER loopback OPTIONS (DROP extensions);
6263 INSERT INTO ft2 (c1,c2,c3)
6264 SELECT id, id % 10, to_char(id, 'FM00000') FROM generate_series(2001, 2010) id;
6265 EXPLAIN (verbose, costs off)
6266 UPDATE ft2 SET c3 = 'bar' WHERE postgres_fdw_abs(c1) > 2000 RETURNING *; -- can't be pushed down
6268 ----------------------------------------------------------------------------------------------------------
6269 Update on public.ft2
6270 Output: c1, c2, c3, c4, c5, c6, c7, c8
6271 Remote SQL: UPDATE "S 1"."T 1" SET c3 = $2 WHERE ctid = $1 RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8
6272 -> Foreign Scan on public.ft2
6273 Output: 'bar'::text, ctid, ft2.*
6274 Filter: (postgres_fdw_abs(ft2.c1) > 2000)
6275 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" FOR UPDATE
6278 UPDATE ft2 SET c3 = 'bar' WHERE postgres_fdw_abs(c1) > 2000 RETURNING *;
6279 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6280 ------+----+-----+----+----+----+------------+----
6281 2001 | 1 | bar | | | | ft2 |
6282 2002 | 2 | bar | | | | ft2 |
6283 2003 | 3 | bar | | | | ft2 |
6284 2004 | 4 | bar | | | | ft2 |
6285 2005 | 5 | bar | | | | ft2 |
6286 2006 | 6 | bar | | | | ft2 |
6287 2007 | 7 | bar | | | | ft2 |
6288 2008 | 8 | bar | | | | ft2 |
6289 2009 | 9 | bar | | | | ft2 |
6290 2010 | 0 | bar | | | | ft2 |
6293 EXPLAIN (verbose, costs off)
6294 UPDATE ft2 SET c3 = 'baz'
6295 FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
6296 WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1
6297 RETURNING ft2.*, ft4.*, ft5.*; -- can't be pushed down
6299 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6300 Update on public.ft2
6301 Output: 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
6302 Remote SQL: UPDATE "S 1"."T 1" SET c3 = $2 WHERE ctid = $1 RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8
6304 Output: 'baz'::text, ft2.ctid, ft2.*, ft4.*, ft5.*, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3
6305 Join Filter: (ft2.c2 === ft4.c1)
6306 -> Foreign Scan on public.ft2
6307 Output: ft2.ctid, ft2.*, ft2.c2
6308 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 2000)) FOR UPDATE
6310 Output: ft4.*, ft4.c1, ft4.c2, ft4.c3, ft5.*, ft5.c1, ft5.c2, ft5.c3
6311 Relations: (public.ft4) INNER JOIN (public.ft5)
6312 Remote SQL: SELECT CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2.c1, r2.c2, r2.c3) END, r2.c1, r2.c2, r2.c3, CASE WHEN (r3.*)::text IS NOT NULL THEN ROW(r3.c1, r3.c2, r3.c3) END, r3.c1, r3.c2, r3.c3 FROM ("S 1"."T 3" r2 INNER JOIN "S 1"."T 4" r3 ON (((r2.c1 = r3.c1))))
6314 Output: ft4.*, ft4.c1, ft4.c2, ft4.c3, ft5.*, ft5.c1, ft5.c2, ft5.c3
6315 Hash Cond: (ft4.c1 = ft5.c1)
6316 -> Foreign Scan on public.ft4
6317 Output: ft4.*, ft4.c1, ft4.c2, ft4.c3
6318 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
6320 Output: ft5.*, ft5.c1, ft5.c2, ft5.c3
6321 -> Foreign Scan on public.ft5
6322 Output: ft5.*, ft5.c1, ft5.c2, ft5.c3
6323 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4"
6326 UPDATE ft2 SET c3 = 'baz'
6327 FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
6328 WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1
6329 RETURNING ft2.*, ft4.*, ft5.*;
6330 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c1 | c2 | c3
6331 ------+----+-----+----+----+----+------------+----+----+----+--------+----+----+--------
6332 2006 | 6 | baz | | | | ft2 | | 6 | 7 | AAA006 | 6 | 7 | AAA006
6335 EXPLAIN (verbose, costs off)
6337 USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1)
6338 WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1
6339 RETURNING ft2.c1, ft2.c2, ft2.c3; -- can't be pushed down
6341 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6342 Delete on public.ft2
6343 Output: ft2.c1, ft2.c2, ft2.c3
6344 Remote SQL: DELETE FROM "S 1"."T 1" WHERE ctid = $1 RETURNING "C 1", c2, c3
6346 Output: ft2.ctid, ft4.*, ft5.*
6347 Filter: (ft4.c1 === ft5.c1)
6348 Relations: ((public.ft2) INNER JOIN (public.ft4)) INNER JOIN (public.ft5)
6349 Remote SQL: SELECT r1.ctid, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2.c1, r2.c2, r2.c3) END, CASE WHEN (r3.*)::text IS NOT NULL THEN ROW(r3.c1, r3.c2, r3.c3) END, r2.c1, r3.c1 FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 3" r2 ON (((r1.c2 = r2.c1)) AND ((r1."C 1" > 2000)))) INNER JOIN "S 1"."T 4" r3 ON (TRUE)) FOR UPDATE OF r1
6351 Output: ft2.ctid, ft4.*, ft5.*, ft4.c1, ft5.c1
6353 Output: ft2.ctid, ft4.*, ft4.c1
6354 Join Filter: (ft2.c2 = ft4.c1)
6355 -> Foreign Scan on public.ft2
6356 Output: ft2.ctid, ft2.c2
6357 Remote SQL: SELECT c2, ctid FROM "S 1"."T 1" WHERE (("C 1" > 2000)) FOR UPDATE
6358 -> Foreign Scan on public.ft4
6359 Output: ft4.*, ft4.c1
6360 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
6361 -> Foreign Scan on public.ft5
6362 Output: ft5.*, ft5.c1
6363 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4"
6367 USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1)
6368 WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1
6369 RETURNING ft2.c1, ft2.c2, ft2.c3;
6375 DELETE FROM ft2 WHERE ft2.c1 > 2000;
6376 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
6377 -- Test that trigger on remote table works as expected
6378 CREATE OR REPLACE FUNCTION "S 1".F_BRTRIG() RETURNS trigger AS $$
6380 NEW.c3 = NEW.c3 || '_trig_update';
6383 $$ LANGUAGE plpgsql;
6384 CREATE TRIGGER t1_br_insert BEFORE INSERT OR UPDATE
6385 ON "S 1"."T 1" FOR EACH ROW EXECUTE PROCEDURE "S 1".F_BRTRIG();
6386 INSERT INTO ft2 (c1,c2,c3) VALUES (1208, 818, 'fff') RETURNING *;
6387 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6388 ------+-----+-----------------+----+----+----+------------+----
6389 1208 | 818 | fff_trig_update | | | | ft2 |
6392 INSERT INTO ft2 (c1,c2,c3,c6) VALUES (1218, 818, 'ggg', '(--;') RETURNING *;
6393 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6394 ------+-----+-----------------+----+----+------+------------+----
6395 1218 | 818 | ggg_trig_update | | | (--; | ft2 |
6398 UPDATE ft2 SET c2 = c2 + 600 WHERE c1 % 10 = 8 AND c1 < 1200 RETURNING *;
6399 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6400 ------+-----+------------------------+------------------------------+--------------------------+----+------------+-----
6401 8 | 608 | 00008_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6402 18 | 608 | 00018_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6403 28 | 608 | 00028_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6404 38 | 608 | 00038_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6405 48 | 608 | 00048_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6406 58 | 608 | 00058_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6407 68 | 608 | 00068_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6408 78 | 608 | 00078_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6409 88 | 608 | 00088_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6410 98 | 608 | 00098_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6411 108 | 608 | 00108_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6412 118 | 608 | 00118_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6413 128 | 608 | 00128_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6414 138 | 608 | 00138_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6415 148 | 608 | 00148_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6416 158 | 608 | 00158_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6417 168 | 608 | 00168_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6418 178 | 608 | 00178_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6419 188 | 608 | 00188_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6420 198 | 608 | 00198_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6421 208 | 608 | 00208_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6422 218 | 608 | 00218_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6423 228 | 608 | 00228_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6424 238 | 608 | 00238_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6425 248 | 608 | 00248_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6426 258 | 608 | 00258_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6427 268 | 608 | 00268_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6428 278 | 608 | 00278_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6429 288 | 608 | 00288_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6430 298 | 608 | 00298_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6431 308 | 608 | 00308_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6432 318 | 608 | 00318_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6433 328 | 608 | 00328_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6434 338 | 608 | 00338_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6435 348 | 608 | 00348_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6436 358 | 608 | 00358_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6437 368 | 608 | 00368_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6438 378 | 608 | 00378_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6439 388 | 608 | 00388_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6440 398 | 608 | 00398_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6441 408 | 608 | 00408_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6442 418 | 608 | 00418_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6443 428 | 608 | 00428_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6444 438 | 608 | 00438_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6445 448 | 608 | 00448_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6446 458 | 608 | 00458_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6447 468 | 608 | 00468_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6448 478 | 608 | 00478_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6449 488 | 608 | 00488_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6450 498 | 608 | 00498_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6451 508 | 608 | 00508_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6452 518 | 608 | 00518_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6453 528 | 608 | 00528_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6454 538 | 608 | 00538_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6455 548 | 608 | 00548_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6456 558 | 608 | 00558_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6457 568 | 608 | 00568_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6458 578 | 608 | 00578_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6459 588 | 608 | 00588_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6460 598 | 608 | 00598_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6461 608 | 608 | 00608_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6462 618 | 608 | 00618_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6463 628 | 608 | 00628_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6464 638 | 608 | 00638_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6465 648 | 608 | 00648_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6466 658 | 608 | 00658_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6467 668 | 608 | 00668_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6468 678 | 608 | 00678_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6469 688 | 608 | 00688_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6470 698 | 608 | 00698_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6471 708 | 608 | 00708_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6472 718 | 608 | 00718_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6473 728 | 608 | 00728_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6474 738 | 608 | 00738_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6475 748 | 608 | 00748_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6476 758 | 608 | 00758_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6477 768 | 608 | 00768_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6478 778 | 608 | 00778_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6479 788 | 608 | 00788_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6480 798 | 608 | 00798_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6481 808 | 608 | 00808_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6482 818 | 608 | 00818_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6483 828 | 608 | 00828_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6484 838 | 608 | 00838_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6485 848 | 608 | 00848_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6486 858 | 608 | 00858_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6487 868 | 608 | 00868_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6488 878 | 608 | 00878_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6489 888 | 608 | 00888_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6490 898 | 608 | 00898_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6491 908 | 608 | 00908_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6492 918 | 608 | 00918_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6493 928 | 608 | 00928_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6494 938 | 608 | 00938_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6495 948 | 608 | 00948_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6496 958 | 608 | 00958_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6497 968 | 608 | 00968_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6498 978 | 608 | 00978_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6499 988 | 608 | 00988_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6500 998 | 608 | 00998_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6501 1008 | 708 | 0000800008_trig_update | | | | ft2 |
6502 1018 | 708 | 0001800018_trig_update | | | | ft2 |
6505 -- Test errors thrown on remote side during update
6506 ALTER TABLE "S 1"."T 1" ADD CONSTRAINT c2positive CHECK (c2 >= 0);
6507 INSERT INTO ft1(c1, c2) VALUES(11, 12); -- duplicate key
6508 ERROR: duplicate key value violates unique constraint "t1_pkey"
6509 DETAIL: Key ("C 1")=(11) already exists.
6510 CONTEXT: remote SQL command: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
6511 INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT DO NOTHING; -- works
6512 INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO NOTHING; -- unsupported
6513 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
6514 INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO UPDATE SET c3 = 'ffg'; -- unsupported
6515 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
6516 INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive
6517 ERROR: new row for relation "T 1" violates check constraint "c2positive"
6518 DETAIL: Failing row contains (1111, -2, null, null, null, null, ft1 , null).
6519 CONTEXT: remote SQL command: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
6520 UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive
6521 ERROR: new row for relation "T 1" violates check constraint "c2positive"
6522 DETAIL: Failing row contains (1, -1, 00001_trig_update, 1970-01-02 08:00:00+00, 1970-01-02 00:00:00, 1, 1 , foo).
6523 CONTEXT: remote SQL command: UPDATE "S 1"."T 1" SET c2 = (- c2) WHERE (("C 1" = 1))
6524 -- Test savepoint/rollback behavior
6525 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6543 select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
6562 update ft2 set c2 = 42 where c2 = 0;
6563 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6582 update ft2 set c2 = 44 where c2 = 4;
6583 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6601 release savepoint s1;
6602 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6621 update ft2 set c2 = 46 where c2 = 6;
6622 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6640 rollback to savepoint s2;
6641 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6659 release savepoint s2;
6660 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6679 update ft2 set c2 = -2 where c2 = 42 and c1 = 10; -- fail on remote side
6680 ERROR: new row for relation "T 1" violates check constraint "c2positive"
6681 DETAIL: Failing row contains (10, -2, 00010_trig_update_trig_update, 1970-01-11 08:00:00+00, 1970-01-11 00:00:00, 0, 0 , foo).
6682 CONTEXT: remote SQL command: UPDATE "S 1"."T 1" SET c2 = (-2) WHERE ((c2 = 42)) AND (("C 1" = 10))
6683 rollback to savepoint s3;
6684 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6702 release savepoint s3;
6703 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6721 -- none of the above is committed yet remotely
6722 select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
6741 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6759 select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
6777 VACUUM ANALYZE "S 1"."T 1";
6778 -- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs
6779 -- FIRST behavior here.
6780 -- ORDER BY DESC NULLS LAST options
6781 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10;
6783 ---------------------------------------------------------------------------------------------------------------------------------------------------------------
6784 Foreign Scan on public.ft1
6785 Output: c1, c2, c3, c4, c5, c6, c7, c8
6786 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" ORDER BY c6 DESC NULLS LAST, "C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 795::bigint
6789 SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10;
6790 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6791 ------+-----+--------------------+------------------------------+--------------------------+------+------------+-----
6792 960 | 42 | 00960_trig_update | Mon Mar 02 00:00:00 1970 PST | Mon Mar 02 00:00:00 1970 | 0 | 0 | foo
6793 970 | 42 | 00970_trig_update | Thu Mar 12 00:00:00 1970 PST | Thu Mar 12 00:00:00 1970 | 0 | 0 | foo
6794 980 | 42 | 00980_trig_update | Sun Mar 22 00:00:00 1970 PST | Sun Mar 22 00:00:00 1970 | 0 | 0 | foo
6795 990 | 42 | 00990_trig_update | Wed Apr 01 00:00:00 1970 PST | Wed Apr 01 00:00:00 1970 | 0 | 0 | foo
6796 1000 | 42 | 01000_trig_update | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0 | 0 | foo
6797 1218 | 818 | ggg_trig_update | | | (--; | ft2 |
6798 1001 | 101 | 0000100001 | | | | ft2 |
6799 1003 | 403 | 0000300003_update3 | | | | ft2 |
6800 1004 | 104 | 0000400004 | | | | ft2 |
6801 1006 | 106 | 0000600006 | | | | ft2 |
6804 -- ORDER BY DESC NULLS FIRST options
6805 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
6807 ---------------------------------------------------------------------------------------------------------------------------------------------------------------
6808 Foreign Scan on public.ft1
6809 Output: c1, c2, c3, c4, c5, c6, c7, c8
6810 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" ORDER BY c6 DESC NULLS FIRST, "C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 15::bigint
6813 SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
6814 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6815 ------+-----+-----------------+------------------------------+--------------------------+----+------------+-----
6816 1020 | 100 | 0002000020 | | | | ft2 |
6817 1101 | 201 | aaa | | | | ft2 |
6818 1103 | 503 | ccc_update3 | | | | ft2 |
6819 1104 | 204 | ddd | | | | ft2 |
6820 1208 | 818 | fff_trig_update | | | | ft2 |
6821 9 | 509 | 00009_update9 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | ft2 | foo
6822 19 | 509 | 00019_update9 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | ft2 | foo
6823 29 | 509 | 00029_update9 | Fri Jan 30 00:00:00 1970 PST | Fri Jan 30 00:00:00 1970 | 9 | ft2 | foo
6824 39 | 509 | 00039_update9 | Mon Feb 09 00:00:00 1970 PST | Mon Feb 09 00:00:00 1970 | 9 | ft2 | foo
6825 49 | 509 | 00049_update9 | Thu Feb 19 00:00:00 1970 PST | Thu Feb 19 00:00:00 1970 | 9 | ft2 | foo
6828 -- ORDER BY ASC NULLS FIRST options
6829 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
6831 --------------------------------------------------------------------------------------------------------------------------------------------------------------
6832 Foreign Scan on public.ft1
6833 Output: c1, c2, c3, c4, c5, c6, c7, c8
6834 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" ORDER BY c6 ASC NULLS FIRST, "C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 15::bigint
6837 SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
6838 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6839 ------+-----+-------------------+------------------------------+--------------------------+------+------------+-----
6840 1020 | 100 | 0002000020 | | | | ft2 |
6841 1101 | 201 | aaa | | | | ft2 |
6842 1103 | 503 | ccc_update3 | | | | ft2 |
6843 1104 | 204 | ddd | | | | ft2 |
6844 1208 | 818 | fff_trig_update | | | | ft2 |
6845 1218 | 818 | ggg_trig_update | | | (--; | ft2 |
6846 10 | 42 | 00010_trig_update | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo
6847 20 | 42 | 00020_trig_update | Wed Jan 21 00:00:00 1970 PST | Wed Jan 21 00:00:00 1970 | 0 | 0 | foo
6848 30 | 42 | 00030_trig_update | Sat Jan 31 00:00:00 1970 PST | Sat Jan 31 00:00:00 1970 | 0 | 0 | foo
6849 40 | 42 | 00040_trig_update | Tue Feb 10 00:00:00 1970 PST | Tue Feb 10 00:00:00 1970 | 0 | 0 | foo
6852 -- ===================================================================
6853 -- test check constraints
6854 -- ===================================================================
6855 -- Consistent check constraints provide consistent results
6856 ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK (c2 >= 0);
6857 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0;
6859 -----------------------------------------------------------------
6862 Relations: Aggregate on (public.ft1)
6863 Remote SQL: SELECT count(*) FROM "S 1"."T 1" WHERE ((c2 < 0))
6866 SELECT count(*) FROM ft1 WHERE c2 < 0;
6872 SET constraint_exclusion = 'on';
6873 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0;
6875 --------------------------------
6879 One-Time Filter: false
6882 SELECT count(*) FROM ft1 WHERE c2 < 0;
6888 RESET constraint_exclusion;
6889 -- check constraint is enforced on the remote side, not locally
6890 INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive
6891 ERROR: new row for relation "T 1" violates check constraint "c2positive"
6892 DETAIL: Failing row contains (1111, -2, null, null, null, null, ft1 , null).
6893 CONTEXT: remote SQL command: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
6894 UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive
6895 ERROR: new row for relation "T 1" violates check constraint "c2positive"
6896 DETAIL: Failing row contains (1, -1, 00001_trig_update, 1970-01-02 08:00:00+00, 1970-01-02 00:00:00, 1, 1 , foo).
6897 CONTEXT: remote SQL command: UPDATE "S 1"."T 1" SET c2 = (- c2) WHERE (("C 1" = 1))
6898 ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive;
6899 -- But inconsistent check constraints provide inconsistent results
6900 ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK (c2 < 0);
6901 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0;
6903 ------------------------------------------------------------------
6906 Relations: Aggregate on (public.ft1)
6907 Remote SQL: SELECT count(*) FROM "S 1"."T 1" WHERE ((c2 >= 0))
6910 SELECT count(*) FROM ft1 WHERE c2 >= 0;
6916 SET constraint_exclusion = 'on';
6917 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0;
6919 --------------------------------
6923 One-Time Filter: false
6926 SELECT count(*) FROM ft1 WHERE c2 >= 0;
6932 RESET constraint_exclusion;
6933 -- local check constraint is not actually enforced
6934 INSERT INTO ft1(c1, c2) VALUES(1111, 2);
6935 UPDATE ft1 SET c2 = c2 + 1 WHERE c1 = 1;
6936 ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2negative;
6937 -- ===================================================================
6938 -- test WITH CHECK OPTION constraints
6939 -- ===================================================================
6940 CREATE FUNCTION row_before_insupd_trigfunc() RETURNS trigger AS $$BEGIN NEW.a := NEW.a + 10; RETURN NEW; END$$ LANGUAGE plpgsql;
6941 CREATE TABLE base_tbl (a int, b int);
6942 ALTER TABLE base_tbl SET (autovacuum_enabled = 'false');
6943 CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON base_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc();
6944 CREATE FOREIGN TABLE foreign_tbl (a int, b int)
6945 SERVER loopback OPTIONS (table_name 'base_tbl');
6946 CREATE VIEW rw_view AS SELECT * FROM foreign_tbl
6947 WHERE a < b WITH CHECK OPTION;
6949 View "public.rw_view"
6950 Column | Type | Collation | Nullable | Default | Storage | Description
6951 --------+---------+-----------+----------+---------+---------+-------------
6952 a | integer | | | | plain |
6953 b | integer | | | | plain |
6959 Options: check_option=cascaded
6961 EXPLAIN (VERBOSE, COSTS OFF)
6962 INSERT INTO rw_view VALUES (0, 5);
6964 --------------------------------------------------------------------------------
6965 Insert on public.foreign_tbl
6966 Remote SQL: INSERT INTO public.base_tbl(a, b) VALUES ($1, $2) RETURNING a, b
6972 INSERT INTO rw_view VALUES (0, 5); -- should fail
6973 ERROR: new row violates check option for view "rw_view"
6974 DETAIL: Failing row contains (10, 5).
6975 EXPLAIN (VERBOSE, COSTS OFF)
6976 INSERT INTO rw_view VALUES (0, 15);
6978 --------------------------------------------------------------------------------
6979 Insert on public.foreign_tbl
6980 Remote SQL: INSERT INTO public.base_tbl(a, b) VALUES ($1, $2) RETURNING a, b
6986 INSERT INTO rw_view VALUES (0, 15); -- ok
6987 SELECT * FROM foreign_tbl;
6993 EXPLAIN (VERBOSE, COSTS OFF)
6994 UPDATE rw_view SET b = b + 5;
6996 ---------------------------------------------------------------------------------------
6997 Update on public.foreign_tbl
6998 Remote SQL: UPDATE public.base_tbl SET b = $2 WHERE ctid = $1 RETURNING a, b
6999 -> Foreign Scan on public.foreign_tbl
7000 Output: (foreign_tbl.b + 5), foreign_tbl.ctid, foreign_tbl.*
7001 Remote SQL: SELECT a, b, ctid FROM public.base_tbl WHERE ((a < b)) FOR UPDATE
7004 UPDATE rw_view SET b = b + 5; -- should fail
7005 ERROR: new row violates check option for view "rw_view"
7006 DETAIL: Failing row contains (20, 20).
7007 EXPLAIN (VERBOSE, COSTS OFF)
7008 UPDATE rw_view SET b = b + 15;
7010 ---------------------------------------------------------------------------------------
7011 Update on public.foreign_tbl
7012 Remote SQL: UPDATE public.base_tbl SET b = $2 WHERE ctid = $1 RETURNING a, b
7013 -> Foreign Scan on public.foreign_tbl
7014 Output: (foreign_tbl.b + 15), foreign_tbl.ctid, foreign_tbl.*
7015 Remote SQL: SELECT a, b, ctid FROM public.base_tbl WHERE ((a < b)) FOR UPDATE
7018 UPDATE rw_view SET b = b + 15; -- ok
7019 SELECT * FROM foreign_tbl;
7025 -- We don't allow batch insert when there are any WCO constraints
7026 ALTER SERVER loopback OPTIONS (ADD batch_size '10');
7027 EXPLAIN (VERBOSE, COSTS OFF)
7028 INSERT INTO rw_view VALUES (0, 15), (0, 5);
7030 --------------------------------------------------------------------------------
7031 Insert on public.foreign_tbl
7032 Remote SQL: INSERT INTO public.base_tbl(a, b) VALUES ($1, $2) RETURNING a, b
7034 -> Values Scan on "*VALUES*"
7035 Output: "*VALUES*".column1, "*VALUES*".column2
7038 INSERT INTO rw_view VALUES (0, 15), (0, 5); -- should fail
7039 ERROR: new row violates check option for view "rw_view"
7040 DETAIL: Failing row contains (10, 5).
7041 SELECT * FROM foreign_tbl;
7047 ALTER SERVER loopback OPTIONS (DROP batch_size);
7048 DROP FOREIGN TABLE foreign_tbl CASCADE;
7049 NOTICE: drop cascades to view rw_view
7050 DROP TRIGGER row_before_insupd_trigger ON base_tbl;
7051 DROP TABLE base_tbl;
7052 -- test WCO for partitions
7053 CREATE TABLE child_tbl (a int, b int);
7054 ALTER TABLE child_tbl SET (autovacuum_enabled = 'false');
7055 CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON child_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc();
7056 CREATE FOREIGN TABLE foreign_tbl (a int, b int)
7057 SERVER loopback OPTIONS (table_name 'child_tbl');
7058 CREATE TABLE parent_tbl (a int, b int) PARTITION BY RANGE(a);
7059 ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100);
7060 -- Detach and re-attach once, to stress the concurrent detach case.
7061 ALTER TABLE parent_tbl DETACH PARTITION foreign_tbl CONCURRENTLY;
7062 ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100);
7063 CREATE VIEW rw_view AS SELECT * FROM parent_tbl
7064 WHERE a < b WITH CHECK OPTION;
7066 View "public.rw_view"
7067 Column | Type | Collation | Nullable | Default | Storage | Description
7068 --------+---------+-----------+----------+---------+---------+-------------
7069 a | integer | | | | plain |
7070 b | integer | | | | plain |
7076 Options: check_option=cascaded
7078 EXPLAIN (VERBOSE, COSTS OFF)
7079 INSERT INTO rw_view VALUES (0, 5);
7081 -----------------------------
7082 Insert on public.parent_tbl
7087 INSERT INTO rw_view VALUES (0, 5); -- should fail
7088 ERROR: new row violates check option for view "rw_view"
7089 DETAIL: Failing row contains (10, 5).
7090 EXPLAIN (VERBOSE, COSTS OFF)
7091 INSERT INTO rw_view VALUES (0, 15);
7093 -----------------------------
7094 Insert on public.parent_tbl
7099 INSERT INTO rw_view VALUES (0, 15); -- ok
7100 SELECT * FROM foreign_tbl;
7106 EXPLAIN (VERBOSE, COSTS OFF)
7107 UPDATE rw_view SET b = b + 5;
7109 ------------------------------------------------------------------------------------------------
7110 Update on public.parent_tbl
7111 Foreign Update on public.foreign_tbl parent_tbl_1
7112 Remote SQL: UPDATE public.child_tbl SET b = $2 WHERE ctid = $1 RETURNING a, b
7113 -> Foreign Scan on public.foreign_tbl parent_tbl_1
7114 Output: (parent_tbl_1.b + 5), parent_tbl_1.tableoid, parent_tbl_1.ctid, parent_tbl_1.*
7115 Remote SQL: SELECT a, b, ctid FROM public.child_tbl WHERE ((a < b)) FOR UPDATE
7118 UPDATE rw_view SET b = b + 5; -- should fail
7119 ERROR: new row violates check option for view "rw_view"
7120 DETAIL: Failing row contains (20, 20).
7121 EXPLAIN (VERBOSE, COSTS OFF)
7122 UPDATE rw_view SET b = b + 15;
7124 -------------------------------------------------------------------------------------------------
7125 Update on public.parent_tbl
7126 Foreign Update on public.foreign_tbl parent_tbl_1
7127 Remote SQL: UPDATE public.child_tbl SET b = $2 WHERE ctid = $1 RETURNING a, b
7128 -> Foreign Scan on public.foreign_tbl parent_tbl_1
7129 Output: (parent_tbl_1.b + 15), parent_tbl_1.tableoid, parent_tbl_1.ctid, parent_tbl_1.*
7130 Remote SQL: SELECT a, b, ctid FROM public.child_tbl WHERE ((a < b)) FOR UPDATE
7133 UPDATE rw_view SET b = b + 15; -- ok
7134 SELECT * FROM foreign_tbl;
7140 -- We don't allow batch insert when there are any WCO constraints
7141 ALTER SERVER loopback OPTIONS (ADD batch_size '10');
7142 EXPLAIN (VERBOSE, COSTS OFF)
7143 INSERT INTO rw_view VALUES (0, 15), (0, 5);
7145 --------------------------------------------------------
7146 Insert on public.parent_tbl
7147 -> Values Scan on "*VALUES*"
7148 Output: "*VALUES*".column1, "*VALUES*".column2
7151 INSERT INTO rw_view VALUES (0, 15), (0, 5); -- should fail
7152 ERROR: new row violates check option for view "rw_view"
7153 DETAIL: Failing row contains (10, 5).
7154 SELECT * FROM foreign_tbl;
7160 ALTER SERVER loopback OPTIONS (DROP batch_size);
7161 DROP FOREIGN TABLE foreign_tbl CASCADE;
7162 DROP TRIGGER row_before_insupd_trigger ON child_tbl;
7163 DROP TABLE parent_tbl CASCADE;
7164 NOTICE: drop cascades to view rw_view
7165 DROP FUNCTION row_before_insupd_trigfunc;
7166 -- Try a more complex permutation of WCO where there are multiple levels of
7167 -- partitioned tables with columns not all in the same order
7168 CREATE TABLE parent_tbl (a int, b text, c numeric) PARTITION BY RANGE(a);
7169 CREATE TABLE sub_parent (c numeric, a int, b text) PARTITION BY RANGE(a);
7170 ALTER TABLE parent_tbl ATTACH PARTITION sub_parent FOR VALUES FROM (1) TO (10);
7171 CREATE TABLE child_local (b text, c numeric, a int);
7172 CREATE FOREIGN TABLE child_foreign (b text, c numeric, a int)
7173 SERVER loopback OPTIONS (table_name 'child_local');
7174 ALTER TABLE sub_parent ATTACH PARTITION child_foreign FOR VALUES FROM (1) TO (10);
7175 CREATE VIEW rw_view AS SELECT * FROM parent_tbl WHERE a < 5 WITH CHECK OPTION;
7176 INSERT INTO parent_tbl (a) VALUES(1),(5);
7177 EXPLAIN (VERBOSE, COSTS OFF)
7178 UPDATE rw_view SET b = 'text', c = 123.456;
7180 -------------------------------------------------------------------------------------------------
7181 Update on public.parent_tbl
7182 Foreign Update on public.child_foreign parent_tbl_1
7183 Remote SQL: UPDATE public.child_local SET b = $2, c = $3 WHERE ctid = $1 RETURNING a
7184 -> Foreign Scan on public.child_foreign parent_tbl_1
7185 Output: 'text'::text, 123.456, parent_tbl_1.tableoid, parent_tbl_1.ctid, parent_tbl_1.*
7186 Remote SQL: SELECT b, c, a, ctid FROM public.child_local WHERE ((a < 5)) FOR UPDATE
7189 UPDATE rw_view SET b = 'text', c = 123.456;
7190 SELECT * FROM parent_tbl ORDER BY a;
7192 ---+------+---------
7198 DROP TABLE child_local;
7199 DROP FOREIGN TABLE child_foreign;
7200 DROP TABLE sub_parent;
7201 DROP TABLE parent_tbl;
7202 -- ===================================================================
7203 -- test serial columns (ie, sequence-based defaults)
7204 -- ===================================================================
7205 create table loc1 (f1 serial, f2 text);
7206 alter table loc1 set (autovacuum_enabled = 'false');
7207 create foreign table rem1 (f1 serial, f2 text)
7208 server loopback options(table_name 'loc1');
7209 select pg_catalog.setval('rem1_f1_seq', 10, false);
7215 insert into loc1(f2) values('hi');
7216 insert into rem1(f2) values('hi remote');
7217 insert into loc1(f2) values('bye');
7218 insert into rem1(f2) values('bye remote');
7237 -- ===================================================================
7238 -- test generated columns
7239 -- ===================================================================
7240 create table gloc1 (
7242 b int generated always as (a * 2) stored);
7243 alter table gloc1 set (autovacuum_enabled = 'false');
7244 create foreign table grem1 (
7246 b int generated always as (a * 2) stored)
7247 server loopback options(table_name 'gloc1');
7248 explain (verbose, costs off)
7249 insert into grem1 (a) values (1), (2);
7251 -------------------------------------------------------------------
7252 Insert on public.grem1
7253 Remote SQL: INSERT INTO public.gloc1(a, b) VALUES ($1, DEFAULT)
7255 -> Values Scan on "*VALUES*"
7256 Output: "*VALUES*".column1, NULL::integer
7259 insert into grem1 (a) values (1), (2);
7260 explain (verbose, costs off)
7261 update grem1 set a = 22 where a = 2;
7263 ------------------------------------------------------------------------------------
7264 Update on public.grem1
7265 Remote SQL: UPDATE public.gloc1 SET a = $2, b = DEFAULT WHERE ctid = $1
7266 -> Foreign Scan on public.grem1
7267 Output: 22, ctid, grem1.*
7268 Remote SQL: SELECT a, b, ctid FROM public.gloc1 WHERE ((a = 2)) FOR UPDATE
7271 update grem1 set a = 22 where a = 2;
7272 select * from gloc1;
7279 select * from grem1;
7288 copy grem1 from stdin;
7289 select * from gloc1;
7296 select * from grem1;
7304 -- test batch insert
7305 alter server loopback options (add batch_size '10');
7306 explain (verbose, costs off)
7307 insert into grem1 (a) values (1), (2);
7309 -------------------------------------------------------------------
7310 Insert on public.grem1
7311 Remote SQL: INSERT INTO public.gloc1(a, b) VALUES ($1, DEFAULT)
7313 -> Values Scan on "*VALUES*"
7314 Output: "*VALUES*".column1, NULL::integer
7317 insert into grem1 (a) values (1), (2);
7318 select * from gloc1;
7325 select * from grem1;
7333 -- batch insert with foreign partitions.
7334 -- This schema uses two partitions, one local and one remote with a modulo
7335 -- to loop across all of them in batches.
7336 create table tab_batch_local (id int, data text);
7337 insert into tab_batch_local select i, 'test'|| i from generate_series(1, 45) i;
7338 create table tab_batch_sharded (id int, data text) partition by hash(id);
7339 create table tab_batch_sharded_p0 partition of tab_batch_sharded
7340 for values with (modulus 2, remainder 0);
7341 create table tab_batch_sharded_p1_remote (id int, data text);
7342 create foreign table tab_batch_sharded_p1 partition of tab_batch_sharded
7343 for values with (modulus 2, remainder 1)
7344 server loopback options (table_name 'tab_batch_sharded_p1_remote');
7345 insert into tab_batch_sharded select * from tab_batch_local;
7346 select count(*) from tab_batch_sharded;
7352 drop table tab_batch_local;
7353 drop table tab_batch_sharded;
7354 drop table tab_batch_sharded_p1_remote;
7355 alter server loopback options (drop batch_size);
7356 -- ===================================================================
7357 -- test local triggers
7358 -- ===================================================================
7359 -- Trigger functions "borrowed" from triggers regress test.
7360 CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$
7362 RAISE NOTICE 'trigger_func(%) called: action = %, when = %, level = %',
7363 TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL;
7366 CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1
7367 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
7368 CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1
7369 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
7370 CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger
7371 LANGUAGE plpgsql AS $$
7379 relid := TG_relid::regclass;
7381 for i in 0 .. TG_nargs - 1 loop
7383 argstr := argstr || ', ';
7385 argstr := argstr || TG_argv[i];
7388 RAISE NOTICE '%(%) % % % ON %',
7389 tg_name, argstr, TG_when, TG_level, TG_OP, relid;
7390 oldnew := '{}'::text[];
7391 if TG_OP != 'INSERT' then
7392 oldnew := array_append(oldnew, format('OLD: %s', OLD));
7395 if TG_OP != 'DELETE' then
7396 oldnew := array_append(oldnew, format('NEW: %s', NEW));
7399 RAISE NOTICE '%', array_to_string(oldnew, ',');
7401 if TG_OP = 'DELETE' then
7408 -- Test basic functionality
7409 CREATE TRIGGER trig_row_before
7410 BEFORE INSERT OR UPDATE OR DELETE ON rem1
7411 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7412 CREATE TRIGGER trig_row_after
7413 AFTER INSERT OR UPDATE OR DELETE ON rem1
7414 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7416 NOTICE: trigger_func(<NULL>) called: action = DELETE, when = BEFORE, level = STATEMENT
7417 NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
7419 NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
7420 NOTICE: OLD: (10,"hi remote")
7421 NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
7422 NOTICE: OLD: (2,bye)
7423 NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
7424 NOTICE: OLD: (11,"bye remote")
7425 NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
7427 NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
7428 NOTICE: OLD: (10,"hi remote")
7429 NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
7430 NOTICE: OLD: (2,bye)
7431 NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
7432 NOTICE: OLD: (11,"bye remote")
7433 NOTICE: trigger_func(<NULL>) called: action = DELETE, when = AFTER, level = STATEMENT
7434 insert into rem1 values(1,'insert');
7435 NOTICE: trigger_func(<NULL>) called: action = INSERT, when = BEFORE, level = STATEMENT
7436 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
7437 NOTICE: NEW: (1,insert)
7438 NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
7439 NOTICE: NEW: (1,insert)
7440 NOTICE: trigger_func(<NULL>) called: action = INSERT, when = AFTER, level = STATEMENT
7441 update rem1 set f2 = 'update' where f1 = 1;
7442 NOTICE: trigger_func(<NULL>) called: action = UPDATE, when = BEFORE, level = STATEMENT
7443 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
7444 NOTICE: OLD: (1,insert),NEW: (1,update)
7445 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
7446 NOTICE: OLD: (1,insert),NEW: (1,update)
7447 NOTICE: trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
7448 update rem1 set f2 = f2 || f2;
7449 NOTICE: trigger_func(<NULL>) called: action = UPDATE, when = BEFORE, level = STATEMENT
7450 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
7451 NOTICE: OLD: (1,update),NEW: (1,updateupdate)
7452 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
7453 NOTICE: OLD: (1,update),NEW: (1,updateupdate)
7454 NOTICE: trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
7456 NOTICE: trigger_func(<NULL>) called: action = TRUNCATE, when = BEFORE, level = STATEMENT
7457 NOTICE: trigger_func(<NULL>) called: action = TRUNCATE, when = AFTER, level = STATEMENT
7459 DROP TRIGGER trig_row_before ON rem1;
7460 DROP TRIGGER trig_row_after ON rem1;
7461 DROP TRIGGER trig_stmt_before ON rem1;
7462 DROP TRIGGER trig_stmt_after ON rem1;
7464 -- Test multiple AFTER ROW triggers on a foreign table
7465 CREATE TRIGGER trig_row_after1
7466 AFTER INSERT OR UPDATE OR DELETE ON rem1
7467 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7468 CREATE TRIGGER trig_row_after2
7469 AFTER INSERT OR UPDATE OR DELETE ON rem1
7470 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7471 insert into rem1 values(1,'insert');
7472 NOTICE: trig_row_after1(23, skidoo) AFTER ROW INSERT ON rem1
7473 NOTICE: NEW: (1,insert)
7474 NOTICE: trig_row_after2(23, skidoo) AFTER ROW INSERT ON rem1
7475 NOTICE: NEW: (1,insert)
7476 update rem1 set f2 = 'update' where f1 = 1;
7477 NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1
7478 NOTICE: OLD: (1,insert),NEW: (1,update)
7479 NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1
7480 NOTICE: OLD: (1,insert),NEW: (1,update)
7481 update rem1 set f2 = f2 || f2;
7482 NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1
7483 NOTICE: OLD: (1,update),NEW: (1,updateupdate)
7484 NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1
7485 NOTICE: OLD: (1,update),NEW: (1,updateupdate)
7487 NOTICE: trig_row_after1(23, skidoo) AFTER ROW DELETE ON rem1
7488 NOTICE: OLD: (1,updateupdate)
7489 NOTICE: trig_row_after2(23, skidoo) AFTER ROW DELETE ON rem1
7490 NOTICE: OLD: (1,updateupdate)
7492 DROP TRIGGER trig_row_after1 ON rem1;
7493 DROP TRIGGER trig_row_after2 ON rem1;
7494 -- Test WHEN conditions
7495 CREATE TRIGGER trig_row_before_insupd
7496 BEFORE INSERT OR UPDATE ON rem1
7498 WHEN (NEW.f2 like '%update%')
7499 EXECUTE PROCEDURE trigger_data(23,'skidoo');
7500 CREATE TRIGGER trig_row_after_insupd
7501 AFTER INSERT OR UPDATE ON rem1
7503 WHEN (NEW.f2 like '%update%')
7504 EXECUTE PROCEDURE trigger_data(23,'skidoo');
7505 -- Insert or update not matching: nothing happens
7506 INSERT INTO rem1 values(1, 'insert');
7507 UPDATE rem1 set f2 = 'test';
7508 -- Insert or update matching: triggers are fired
7509 INSERT INTO rem1 values(2, 'update');
7510 NOTICE: trig_row_before_insupd(23, skidoo) BEFORE ROW INSERT ON rem1
7511 NOTICE: NEW: (2,update)
7512 NOTICE: trig_row_after_insupd(23, skidoo) AFTER ROW INSERT ON rem1
7513 NOTICE: NEW: (2,update)
7514 UPDATE rem1 set f2 = 'update update' where f1 = '2';
7515 NOTICE: trig_row_before_insupd(23, skidoo) BEFORE ROW UPDATE ON rem1
7516 NOTICE: OLD: (2,update),NEW: (2,"update update")
7517 NOTICE: trig_row_after_insupd(23, skidoo) AFTER ROW UPDATE ON rem1
7518 NOTICE: OLD: (2,update),NEW: (2,"update update")
7519 CREATE TRIGGER trig_row_before_delete
7520 BEFORE DELETE ON rem1
7522 WHEN (OLD.f2 like '%update%')
7523 EXECUTE PROCEDURE trigger_data(23,'skidoo');
7524 CREATE TRIGGER trig_row_after_delete
7525 AFTER DELETE ON rem1
7527 WHEN (OLD.f2 like '%update%')
7528 EXECUTE PROCEDURE trigger_data(23,'skidoo');
7529 -- Trigger is fired for f1=2, not for f1=1
7531 NOTICE: trig_row_before_delete(23, skidoo) BEFORE ROW DELETE ON rem1
7532 NOTICE: OLD: (2,"update update")
7533 NOTICE: trig_row_after_delete(23, skidoo) AFTER ROW DELETE ON rem1
7534 NOTICE: OLD: (2,"update update")
7536 DROP TRIGGER trig_row_before_insupd ON rem1;
7537 DROP TRIGGER trig_row_after_insupd ON rem1;
7538 DROP TRIGGER trig_row_before_delete ON rem1;
7539 DROP TRIGGER trig_row_after_delete ON rem1;
7540 -- Test various RETURN statements in BEFORE triggers.
7541 CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$
7543 NEW.f2 := NEW.f2 || ' triggered !';
7546 $$ language plpgsql;
7547 CREATE TRIGGER trig_row_before_insupd
7548 BEFORE INSERT OR UPDATE ON rem1
7549 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
7550 -- The new values should have 'triggered' appended
7551 INSERT INTO rem1 values(1, 'insert');
7554 ----+--------------------
7555 1 | insert triggered !
7558 INSERT INTO rem1 values(2, 'insert') RETURNING f2;
7560 --------------------
7566 ----+--------------------
7567 1 | insert triggered !
7568 2 | insert triggered !
7571 UPDATE rem1 set f2 = '';
7579 UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
7581 --------------------
7588 ----+--------------------
7589 1 | skidoo triggered !
7590 2 | skidoo triggered !
7593 EXPLAIN (verbose, costs off)
7594 UPDATE rem1 set f1 = 10; -- all columns should be transmitted
7596 -----------------------------------------------------------------------
7597 Update on public.rem1
7598 Remote SQL: UPDATE public.loc1 SET f1 = $2, f2 = $3 WHERE ctid = $1
7599 -> Foreign Scan on public.rem1
7600 Output: 10, ctid, rem1.*
7601 Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
7604 UPDATE rem1 set f1 = 10;
7607 ----+--------------------------------
7608 10 | skidoo triggered ! triggered !
7609 10 | skidoo triggered ! triggered !
7613 -- Add a second trigger, to check that the changes are propagated correctly
7614 -- from trigger to trigger
7615 CREATE TRIGGER trig_row_before_insupd2
7616 BEFORE INSERT OR UPDATE ON rem1
7617 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
7618 INSERT INTO rem1 values(1, 'insert');
7621 ----+--------------------------------
7622 1 | insert triggered ! triggered !
7625 INSERT INTO rem1 values(2, 'insert') RETURNING f2;
7627 --------------------------------
7628 insert triggered ! triggered !
7633 ----+--------------------------------
7634 1 | insert triggered ! triggered !
7635 2 | insert triggered ! triggered !
7638 UPDATE rem1 set f2 = '';
7641 ----+--------------------------
7642 1 | triggered ! triggered !
7643 2 | triggered ! triggered !
7646 UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
7648 --------------------------------
7649 skidoo triggered ! triggered !
7650 skidoo triggered ! triggered !
7655 ----+--------------------------------
7656 1 | skidoo triggered ! triggered !
7657 2 | skidoo triggered ! triggered !
7660 DROP TRIGGER trig_row_before_insupd ON rem1;
7661 DROP TRIGGER trig_row_before_insupd2 ON rem1;
7663 INSERT INTO rem1 VALUES (1, 'test');
7664 -- Test with a trigger returning NULL
7665 CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$
7669 $$ language plpgsql;
7670 CREATE TRIGGER trig_null
7671 BEFORE INSERT OR UPDATE OR DELETE ON rem1
7672 FOR EACH ROW EXECUTE PROCEDURE trig_null();
7673 -- Nothing should have changed.
7674 INSERT INTO rem1 VALUES (2, 'test2');
7681 UPDATE rem1 SET f2 = 'test2';
7695 DROP TRIGGER trig_null ON rem1;
7697 -- Test a combination of local and remote triggers
7698 CREATE TRIGGER trig_row_before
7699 BEFORE INSERT OR UPDATE OR DELETE ON rem1
7700 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7701 CREATE TRIGGER trig_row_after
7702 AFTER INSERT OR UPDATE OR DELETE ON rem1
7703 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7704 CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON loc1
7705 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
7706 INSERT INTO rem1(f2) VALUES ('test');
7707 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
7708 NOTICE: NEW: (12,test)
7709 NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
7710 NOTICE: NEW: (12,"test triggered !")
7711 UPDATE rem1 SET f2 = 'testo';
7712 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
7713 NOTICE: OLD: (12,"test triggered !"),NEW: (12,testo)
7714 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
7715 NOTICE: OLD: (12,"test triggered !"),NEW: (12,"testo triggered !")
7716 -- Test returning a system attribute
7717 INSERT INTO rem1(f2) VALUES ('test') RETURNING ctid;
7718 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
7719 NOTICE: NEW: (13,test)
7720 NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
7721 NOTICE: NEW: (13,"test triggered !")
7728 DROP TRIGGER trig_row_before ON rem1;
7729 DROP TRIGGER trig_row_after ON rem1;
7730 DROP TRIGGER trig_local_before ON loc1;
7731 -- Test direct foreign table modification functionality
7732 EXPLAIN (verbose, costs off)
7733 DELETE FROM rem1; -- can be pushed down
7735 ---------------------------------------------
7736 Delete on public.rem1
7737 -> Foreign Delete on public.rem1
7738 Remote SQL: DELETE FROM public.loc1
7741 EXPLAIN (verbose, costs off)
7742 DELETE FROM rem1 WHERE false; -- currently can't be pushed down
7744 -------------------------------------------------------
7745 Delete on public.rem1
7746 Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1
7749 One-Time Filter: false
7752 -- Test with statement-level triggers
7753 CREATE TRIGGER trig_stmt_before
7754 BEFORE DELETE OR INSERT OR UPDATE ON rem1
7755 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
7756 EXPLAIN (verbose, costs off)
7757 UPDATE rem1 set f2 = ''; -- can be pushed down
7759 ----------------------------------------------------------
7760 Update on public.rem1
7761 -> Foreign Update on public.rem1
7762 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7765 EXPLAIN (verbose, costs off)
7766 DELETE FROM rem1; -- can be pushed down
7768 ---------------------------------------------
7769 Delete on public.rem1
7770 -> Foreign Delete on public.rem1
7771 Remote SQL: DELETE FROM public.loc1
7774 DROP TRIGGER trig_stmt_before ON rem1;
7775 CREATE TRIGGER trig_stmt_after
7776 AFTER DELETE OR INSERT OR UPDATE ON rem1
7777 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
7778 EXPLAIN (verbose, costs off)
7779 UPDATE rem1 set f2 = ''; -- can be pushed down
7781 ----------------------------------------------------------
7782 Update on public.rem1
7783 -> Foreign Update on public.rem1
7784 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7787 EXPLAIN (verbose, costs off)
7788 DELETE FROM rem1; -- can be pushed down
7790 ---------------------------------------------
7791 Delete on public.rem1
7792 -> Foreign Delete on public.rem1
7793 Remote SQL: DELETE FROM public.loc1
7796 DROP TRIGGER trig_stmt_after ON rem1;
7797 -- Test with row-level ON INSERT triggers
7798 CREATE TRIGGER trig_row_before_insert
7799 BEFORE INSERT ON rem1
7800 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7801 EXPLAIN (verbose, costs off)
7802 UPDATE rem1 set f2 = ''; -- can be pushed down
7804 ----------------------------------------------------------
7805 Update on public.rem1
7806 -> Foreign Update on public.rem1
7807 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7810 EXPLAIN (verbose, costs off)
7811 DELETE FROM rem1; -- can be pushed down
7813 ---------------------------------------------
7814 Delete on public.rem1
7815 -> Foreign Delete on public.rem1
7816 Remote SQL: DELETE FROM public.loc1
7819 DROP TRIGGER trig_row_before_insert ON rem1;
7820 CREATE TRIGGER trig_row_after_insert
7821 AFTER INSERT ON rem1
7822 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7823 EXPLAIN (verbose, costs off)
7824 UPDATE rem1 set f2 = ''; -- can be pushed down
7826 ----------------------------------------------------------
7827 Update on public.rem1
7828 -> Foreign Update on public.rem1
7829 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7832 EXPLAIN (verbose, costs off)
7833 DELETE FROM rem1; -- can be pushed down
7835 ---------------------------------------------
7836 Delete on public.rem1
7837 -> Foreign Delete on public.rem1
7838 Remote SQL: DELETE FROM public.loc1
7841 DROP TRIGGER trig_row_after_insert ON rem1;
7842 -- Test with row-level ON UPDATE triggers
7843 CREATE TRIGGER trig_row_before_update
7844 BEFORE UPDATE ON rem1
7845 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7846 EXPLAIN (verbose, costs off)
7847 UPDATE rem1 set f2 = ''; -- can't be pushed down
7849 -----------------------------------------------------------------------
7850 Update on public.rem1
7851 Remote SQL: UPDATE public.loc1 SET f1 = $2, f2 = $3 WHERE ctid = $1
7852 -> Foreign Scan on public.rem1
7853 Output: ''::text, ctid, rem1.*
7854 Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
7857 EXPLAIN (verbose, costs off)
7858 DELETE FROM rem1; -- can be pushed down
7860 ---------------------------------------------
7861 Delete on public.rem1
7862 -> Foreign Delete on public.rem1
7863 Remote SQL: DELETE FROM public.loc1
7866 DROP TRIGGER trig_row_before_update ON rem1;
7867 CREATE TRIGGER trig_row_after_update
7868 AFTER UPDATE ON rem1
7869 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7870 EXPLAIN (verbose, costs off)
7871 UPDATE rem1 set f2 = ''; -- can't be pushed down
7873 -------------------------------------------------------------------------------
7874 Update on public.rem1
7875 Remote SQL: UPDATE public.loc1 SET f2 = $2 WHERE ctid = $1 RETURNING f1, f2
7876 -> Foreign Scan on public.rem1
7877 Output: ''::text, ctid, rem1.*
7878 Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
7881 EXPLAIN (verbose, costs off)
7882 DELETE FROM rem1; -- can be pushed down
7884 ---------------------------------------------
7885 Delete on public.rem1
7886 -> Foreign Delete on public.rem1
7887 Remote SQL: DELETE FROM public.loc1
7890 DROP TRIGGER trig_row_after_update ON rem1;
7891 -- Test with row-level ON DELETE triggers
7892 CREATE TRIGGER trig_row_before_delete
7893 BEFORE DELETE ON rem1
7894 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7895 EXPLAIN (verbose, costs off)
7896 UPDATE rem1 set f2 = ''; -- can be pushed down
7898 ----------------------------------------------------------
7899 Update on public.rem1
7900 -> Foreign Update on public.rem1
7901 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7904 EXPLAIN (verbose, costs off)
7905 DELETE FROM rem1; -- can't be pushed down
7907 ---------------------------------------------------------------------
7908 Delete on public.rem1
7909 Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1
7910 -> Foreign Scan on public.rem1
7911 Output: ctid, rem1.*
7912 Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
7915 DROP TRIGGER trig_row_before_delete ON rem1;
7916 CREATE TRIGGER trig_row_after_delete
7917 AFTER DELETE ON rem1
7918 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7919 EXPLAIN (verbose, costs off)
7920 UPDATE rem1 set f2 = ''; -- can be pushed down
7922 ----------------------------------------------------------
7923 Update on public.rem1
7924 -> Foreign Update on public.rem1
7925 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7928 EXPLAIN (verbose, costs off)
7929 DELETE FROM rem1; -- can't be pushed down
7931 ------------------------------------------------------------------------
7932 Delete on public.rem1
7933 Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1 RETURNING f1, f2
7934 -> Foreign Scan on public.rem1
7935 Output: ctid, rem1.*
7936 Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
7939 DROP TRIGGER trig_row_after_delete ON rem1;
7940 -- ===================================================================
7941 -- test inheritance features
7942 -- ===================================================================
7943 CREATE TABLE a (aa TEXT);
7944 CREATE TABLE loct (aa TEXT, bb TEXT);
7945 ALTER TABLE a SET (autovacuum_enabled = 'false');
7946 ALTER TABLE loct SET (autovacuum_enabled = 'false');
7947 CREATE FOREIGN TABLE b (bb TEXT) INHERITS (a)
7948 SERVER loopback OPTIONS (table_name 'loct');
7949 INSERT INTO a(aa) VALUES('aaa');
7950 INSERT INTO a(aa) VALUES('aaaa');
7951 INSERT INTO a(aa) VALUES('aaaaa');
7952 INSERT INTO b(aa) VALUES('bbb');
7953 INSERT INTO b(aa) VALUES('bbbb');
7954 INSERT INTO b(aa) VALUES('bbbbb');
7955 SELECT tableoid::regclass, * FROM a;
7966 SELECT tableoid::regclass, * FROM b;
7968 ----------+-------+----
7974 SELECT tableoid::regclass, * FROM ONLY a;
7982 UPDATE a SET aa = 'zzzzzz' WHERE aa LIKE 'aaaa%';
7983 SELECT tableoid::regclass, * FROM a;
7994 SELECT tableoid::regclass, * FROM b;
7996 ----------+-------+----
8002 SELECT tableoid::regclass, * FROM ONLY a;
8010 UPDATE b SET aa = 'new';
8011 SELECT tableoid::regclass, * FROM a;
8022 SELECT tableoid::regclass, * FROM b;
8024 ----------+-----+----
8030 SELECT tableoid::regclass, * FROM ONLY a;
8038 UPDATE a SET aa = 'newtoo';
8039 SELECT tableoid::regclass, * FROM a;
8050 SELECT tableoid::regclass, * FROM b;
8052 ----------+--------+----
8058 SELECT tableoid::regclass, * FROM ONLY a;
8067 SELECT tableoid::regclass, * FROM a;
8072 SELECT tableoid::regclass, * FROM b;
8074 ----------+----+----
8077 SELECT tableoid::regclass, * FROM ONLY a;
8082 DROP TABLE a CASCADE;
8083 NOTICE: drop cascades to foreign table b
8085 -- Check SELECT FOR UPDATE/SHARE with an inherited source table
8086 create table loct1 (f1 int, f2 int, f3 int);
8087 create table loct2 (f1 int, f2 int, f3 int);
8088 alter table loct1 set (autovacuum_enabled = 'false');
8089 alter table loct2 set (autovacuum_enabled = 'false');
8090 create table foo (f1 int, f2 int);
8091 create foreign table foo2 (f3 int) inherits (foo)
8092 server loopback options (table_name 'loct1');
8093 create table bar (f1 int, f2 int);
8094 create foreign table bar2 (f3 int) inherits (bar)
8095 server loopback options (table_name 'loct2');
8096 alter table foo set (autovacuum_enabled = 'false');
8097 alter table bar set (autovacuum_enabled = 'false');
8098 insert into foo values(1,1);
8099 insert into foo values(3,3);
8100 insert into foo2 values(2,2,2);
8101 insert into foo2 values(4,4,4);
8102 insert into bar values(1,11);
8103 insert into bar values(2,22);
8104 insert into bar values(6,66);
8105 insert into bar2 values(3,33,33);
8106 insert into bar2 values(4,44,44);
8107 insert into bar2 values(7,77,77);
8108 explain (verbose, costs off)
8109 select * from bar where f1 in (select f1 from foo) for update;
8111 ----------------------------------------------------------------------------------------------
8113 Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid
8115 Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid
8117 Hash Cond: (bar.f1 = foo.f1)
8119 -> Seq Scan on public.bar bar_1
8120 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
8121 -> Foreign Scan on public.bar2 bar_2
8122 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
8123 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
8125 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8127 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8130 -> Seq Scan on public.foo foo_1
8131 Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid
8132 -> Foreign Scan on public.foo2 foo_2
8133 Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid
8134 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
8137 select * from bar where f1 in (select f1 from foo) for update;
8146 explain (verbose, costs off)
8147 select * from bar where f1 in (select f1 from foo) for share;
8149 ----------------------------------------------------------------------------------------------
8151 Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid
8153 Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid
8155 Hash Cond: (bar.f1 = foo.f1)
8157 -> Seq Scan on public.bar bar_1
8158 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
8159 -> Foreign Scan on public.bar2 bar_2
8160 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
8161 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
8163 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8165 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8168 -> Seq Scan on public.foo foo_1
8169 Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid
8170 -> Foreign Scan on public.foo2 foo_2
8171 Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid
8172 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
8175 select * from bar where f1 in (select f1 from foo) for share;
8184 -- Now check SELECT FOR UPDATE/SHARE with an inherited source table,
8185 -- where the parent is itself a foreign table
8186 create table loct4 (f1 int, f2 int, f3 int);
8187 create foreign table foo2child (f3 int) inherits (foo2)
8188 server loopback options (table_name 'loct4');
8189 NOTICE: moving and merging column "f3" with inherited definition
8190 DETAIL: User-specified column moved to the position of the inherited column.
8191 explain (verbose, costs off)
8192 select * from bar where f1 in (select f1 from foo2) for share;
8194 --------------------------------------------------------------------------------------
8196 Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.tableoid
8198 Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.tableoid
8200 Hash Cond: (bar.f1 = foo2.f1)
8202 -> Seq Scan on public.bar bar_1
8203 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
8204 -> Foreign Scan on public.bar2 bar_2
8205 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
8206 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
8208 Output: foo2.*, foo2.f1, foo2.tableoid
8210 Output: foo2.*, foo2.f1, foo2.tableoid
8213 -> Foreign Scan on public.foo2 foo2_1
8214 Output: foo2_1.*, foo2_1.f1, foo2_1.tableoid
8215 Remote SQL: SELECT f1, f2, f3 FROM public.loct1
8216 -> Foreign Scan on public.foo2child foo2_2
8217 Output: foo2_2.*, foo2_2.f1, foo2_2.tableoid
8218 Remote SQL: SELECT f1, f2, f3 FROM public.loct4
8221 select * from bar where f1 in (select f1 from foo2) for share;
8228 drop foreign table foo2child;
8229 -- And with a local child relation of the foreign table parent
8230 create table foo2child (f3 int) inherits (foo2);
8231 NOTICE: moving and merging column "f3" with inherited definition
8232 DETAIL: User-specified column moved to the position of the inherited column.
8233 explain (verbose, costs off)
8234 select * from bar where f1 in (select f1 from foo2) for share;
8236 -------------------------------------------------------------------------------------------------
8238 Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.ctid, foo2.tableoid
8240 Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.ctid, foo2.tableoid
8242 Hash Cond: (bar.f1 = foo2.f1)
8244 -> Seq Scan on public.bar bar_1
8245 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
8246 -> Foreign Scan on public.bar2 bar_2
8247 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
8248 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
8250 Output: foo2.*, foo2.f1, foo2.ctid, foo2.tableoid
8252 Output: foo2.*, foo2.f1, foo2.ctid, foo2.tableoid
8255 -> Foreign Scan on public.foo2 foo2_1
8256 Output: foo2_1.*, foo2_1.f1, foo2_1.ctid, foo2_1.tableoid
8257 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
8258 -> Seq Scan on public.foo2child foo2_2
8259 Output: foo2_2.*, foo2_2.f1, foo2_2.ctid, foo2_2.tableoid
8262 select * from bar where f1 in (select f1 from foo2) for share;
8269 drop table foo2child;
8270 -- Check UPDATE with inherited target and an inherited source table
8271 explain (verbose, costs off)
8272 update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
8274 -------------------------------------------------------------------------------------------------------
8275 Update on public.bar
8276 Update on public.bar bar_1
8277 Foreign Update on public.bar2 bar_2
8278 Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
8280 Output: (bar.f2 + 100), foo.ctid, bar.tableoid, bar.ctid, (NULL::record), foo.*, foo.tableoid
8282 Hash Cond: (bar.f1 = foo.f1)
8284 -> Seq Scan on public.bar bar_1
8285 Output: bar_1.f2, bar_1.f1, bar_1.tableoid, bar_1.ctid, NULL::record
8286 -> Foreign Scan on public.bar2 bar_2
8287 Output: bar_2.f2, bar_2.f1, bar_2.tableoid, bar_2.ctid, bar_2.*
8288 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
8290 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8292 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8295 -> Seq Scan on public.foo foo_1
8296 Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid
8297 -> Foreign Scan on public.foo2 foo_2
8298 Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid
8299 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
8302 update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
8303 select tableoid::regclass, * from bar order by 1,2;
8305 ----------+----+-----
8314 -- Check UPDATE with inherited target and an appendrel subquery
8315 explain (verbose, costs off)
8316 update bar set f2 = f2 + 100
8318 ( select f1 from foo union all select f1+3 from foo ) ss
8319 where bar.f1 = ss.f1;
8321 ------------------------------------------------------------------------------------------------
8322 Update on public.bar
8323 Update on public.bar bar_1
8324 Foreign Update on public.bar2 bar_2
8325 Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
8327 Output: (bar.f2 + 100), (ROW(foo.f1)), bar.tableoid, bar.ctid, (NULL::record)
8328 Merge Cond: (bar.f1 = foo.f1)
8330 Output: bar.f2, bar.f1, bar.tableoid, bar.ctid, (NULL::record)
8333 -> Seq Scan on public.bar bar_1
8334 Output: bar_1.f2, bar_1.f1, bar_1.tableoid, bar_1.ctid, NULL::record
8335 -> Foreign Scan on public.bar2 bar_2
8336 Output: bar_2.f2, bar_2.f1, bar_2.tableoid, bar_2.ctid, bar_2.*
8337 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
8339 Output: (ROW(foo.f1)), foo.f1
8342 -> Seq Scan on public.foo
8343 Output: ROW(foo.f1), foo.f1
8344 -> Foreign Scan on public.foo2 foo_1
8345 Output: ROW(foo_1.f1), foo_1.f1
8346 Remote SQL: SELECT f1 FROM public.loct1
8347 -> Seq Scan on public.foo foo_2
8348 Output: ROW((foo_2.f1 + 3)), (foo_2.f1 + 3)
8349 -> Foreign Scan on public.foo2 foo_3
8350 Output: ROW((foo_3.f1 + 3)), (foo_3.f1 + 3)
8351 Remote SQL: SELECT f1 FROM public.loct1
8354 update bar set f2 = f2 + 100
8356 ( select f1 from foo union all select f1+3 from foo ) ss
8357 where bar.f1 = ss.f1;
8358 select tableoid::regclass, * from bar order by 1,2;
8360 ----------+----+-----
8369 -- Test forcing the remote server to produce sorted data for a merge join,
8370 -- but the foreign table is an inheritance child.
8371 truncate table loct1;
8372 truncate table only foo;
8373 \set num_rows_foo 2000
8374 insert into loct1 select generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2);
8375 insert into foo select generate_series(1, :num_rows_foo, 2), generate_series(1, :num_rows_foo, 2);
8376 SET enable_hashjoin to false;
8377 SET enable_nestloop to false;
8378 alter foreign table foo2 options (use_remote_estimate 'true');
8379 create index i_loct1_f1 on loct1(f1);
8380 create index i_foo_f1 on foo(f1);
8383 -- inner join; expressions in the clauses appear in the equivalence class list
8384 explain (verbose, costs off)
8385 select foo.f1, loct1.f1 from foo join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
8387 --------------------------------------------------------------------------------------------------
8389 Output: foo.f1, loct1.f1, foo.f2
8391 Output: foo.f1, loct1.f1, foo.f2
8394 Output: foo.f1, loct1.f1, foo.f2
8395 Merge Cond: (foo.f1 = loct1.f1)
8398 -> Index Scan using i_foo_f1 on public.foo foo_1
8399 Output: foo_1.f1, foo_1.f2
8400 -> Foreign Scan on public.foo2 foo_2
8401 Output: foo_2.f1, foo_2.f2
8402 Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
8403 -> Index Only Scan using i_loct1_f1 on public.loct1
8407 select foo.f1, loct1.f1 from foo join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
8422 -- outer join; expressions in the clauses do not appear in equivalence class
8423 -- list but no output change as compared to the previous query
8424 explain (verbose, costs off)
8425 select foo.f1, loct1.f1 from foo left join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
8427 --------------------------------------------------------------------------------------------------
8429 Output: foo.f1, loct1.f1, foo.f2
8431 Output: foo.f1, loct1.f1, foo.f2
8434 Output: foo.f1, loct1.f1, foo.f2
8435 Merge Cond: (foo.f1 = loct1.f1)
8438 -> Index Scan using i_foo_f1 on public.foo foo_1
8439 Output: foo_1.f1, foo_1.f2
8440 -> Foreign Scan on public.foo2 foo_2
8441 Output: foo_2.f1, foo_2.f2
8442 Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
8443 -> Index Only Scan using i_loct1_f1 on public.loct1
8447 select foo.f1, loct1.f1 from foo left join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
8462 RESET enable_hashjoin;
8463 RESET enable_nestloop;
8464 -- Test that WHERE CURRENT OF is not supported
8466 declare c cursor for select * from bar where f1 = 7;
8473 update bar set f2 = null where current of c;
8474 ERROR: WHERE CURRENT OF is not supported for this table type
8476 explain (verbose, costs off)
8477 delete from foo where f1 < 5 returning *;
8479 --------------------------------------------------------------------------------------
8480 Delete on public.foo
8481 Output: foo_1.f1, foo_1.f2
8482 Delete on public.foo foo_1
8483 Foreign Delete on public.foo2 foo_2
8485 -> Index Scan using i_foo_f1 on public.foo foo_1
8486 Output: foo_1.tableoid, foo_1.ctid
8487 Index Cond: (foo_1.f1 < 5)
8488 -> Foreign Delete on public.foo2 foo_2
8489 Remote SQL: DELETE FROM public.loct1 WHERE ((f1 < 5)) RETURNING f1, f2
8492 delete from foo where f1 < 5 returning *;
8502 explain (verbose, costs off)
8503 update bar set f2 = f2 + 100 returning *;
8505 ------------------------------------------------------------------------------------------
8506 Update on public.bar
8507 Output: bar_1.f1, bar_1.f2
8508 Update on public.bar bar_1
8509 Foreign Update on public.bar2 bar_2
8511 Output: (bar.f2 + 100), bar.tableoid, bar.ctid, (NULL::record)
8513 -> Seq Scan on public.bar bar_1
8514 Output: bar_1.f2, bar_1.tableoid, bar_1.ctid, NULL::record
8515 -> Foreign Update on public.bar2 bar_2
8516 Remote SQL: UPDATE public.loct2 SET f2 = (f2 + 100) RETURNING f1, f2
8519 update bar set f2 = f2 + 100 returning *;
8530 -- Test that UPDATE/DELETE with inherited target works with row-level triggers
8531 CREATE TRIGGER trig_row_before
8532 BEFORE UPDATE OR DELETE ON bar2
8533 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
8534 CREATE TRIGGER trig_row_after
8535 AFTER UPDATE OR DELETE ON bar2
8536 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
8537 explain (verbose, costs off)
8538 update bar set f2 = f2 + 100;
8540 --------------------------------------------------------------------------------------------------------
8541 Update on public.bar
8542 Update on public.bar bar_1
8543 Foreign Update on public.bar2 bar_2
8544 Remote SQL: UPDATE public.loct2 SET f1 = $2, f2 = $3, f3 = $4 WHERE ctid = $1 RETURNING f1, f2, f3
8546 Output: (bar.f2 + 100), bar.tableoid, bar.ctid, (NULL::record)
8548 -> Seq Scan on public.bar bar_1
8549 Output: bar_1.f2, bar_1.tableoid, bar_1.ctid, NULL::record
8550 -> Foreign Scan on public.bar2 bar_2
8551 Output: bar_2.f2, bar_2.tableoid, bar_2.ctid, bar_2.*
8552 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
8555 update bar set f2 = f2 + 100;
8556 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
8557 NOTICE: OLD: (3,333,33),NEW: (3,433,33)
8558 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
8559 NOTICE: OLD: (4,344,44),NEW: (4,444,44)
8560 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
8561 NOTICE: OLD: (7,277,77),NEW: (7,377,77)
8562 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
8563 NOTICE: OLD: (3,333,33),NEW: (3,433,33)
8564 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
8565 NOTICE: OLD: (4,344,44),NEW: (4,444,44)
8566 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
8567 NOTICE: OLD: (7,277,77),NEW: (7,377,77)
8568 explain (verbose, costs off)
8569 delete from bar where f2 < 400;
8571 ---------------------------------------------------------------------------------------------------
8572 Delete on public.bar
8573 Delete on public.bar bar_1
8574 Foreign Delete on public.bar2 bar_2
8575 Remote SQL: DELETE FROM public.loct2 WHERE ctid = $1 RETURNING f1, f2, f3
8577 -> Seq Scan on public.bar bar_1
8578 Output: bar_1.tableoid, bar_1.ctid, NULL::record
8579 Filter: (bar_1.f2 < 400)
8580 -> Foreign Scan on public.bar2 bar_2
8581 Output: bar_2.tableoid, bar_2.ctid, bar_2.*
8582 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 WHERE ((f2 < 400)) FOR UPDATE
8585 delete from bar where f2 < 400;
8586 NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON bar2
8587 NOTICE: OLD: (7,377,77)
8588 NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON bar2
8589 NOTICE: OLD: (7,377,77)
8591 drop table foo cascade;
8592 NOTICE: drop cascades to foreign table foo2
8593 drop table bar cascade;
8594 NOTICE: drop cascades to foreign table bar2
8597 -- Test pushing down UPDATE/DELETE joins to the remote server
8598 create table parent (a int, b text);
8599 create table loct1 (a int, b text);
8600 create table loct2 (a int, b text);
8601 create foreign table remt1 (a int, b text)
8602 server loopback options (table_name 'loct1');
8603 create foreign table remt2 (a int, b text)
8604 server loopback options (table_name 'loct2');
8605 alter foreign table remt1 inherit parent;
8606 insert into remt1 values (1, 'foo');
8607 insert into remt1 values (2, 'bar');
8608 insert into remt2 values (1, 'foo');
8609 insert into remt2 values (2, 'bar');
8612 explain (verbose, costs off)
8613 update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a returning *;
8615 ----------------------------------------------------------------------------------------------------------------
8616 Update on public.parent
8617 Output: parent_1.a, parent_1.b, remt2.a, remt2.b
8618 Update on public.parent parent_1
8619 Foreign Update on public.remt1 parent_2
8620 Remote SQL: UPDATE public.loct1 SET b = $2 WHERE ctid = $1 RETURNING a, b
8622 Output: (parent.b || remt2.b), remt2.*, remt2.a, remt2.b, parent.tableoid, parent.ctid, (NULL::record)
8623 Join Filter: (parent.a = remt2.a)
8625 -> Seq Scan on public.parent parent_1
8626 Output: parent_1.b, parent_1.a, parent_1.tableoid, parent_1.ctid, NULL::record
8627 -> Foreign Scan on public.remt1 parent_2
8628 Output: parent_2.b, parent_2.a, parent_2.tableoid, parent_2.ctid, parent_2.*
8629 Remote SQL: SELECT a, b, ctid FROM public.loct1 FOR UPDATE
8631 Output: remt2.b, remt2.*, remt2.a
8632 -> Foreign Scan on public.remt2
8633 Output: remt2.b, remt2.*, remt2.a
8634 Remote SQL: SELECT a, b FROM public.loct2
8637 update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a returning *;
8639 ---+--------+---+-----
8640 1 | foofoo | 1 | foo
8641 2 | barbar | 2 | bar
8644 explain (verbose, costs off)
8645 delete from parent using remt2 where parent.a = remt2.a returning parent;
8647 -----------------------------------------------------------------------------
8648 Delete on public.parent
8650 Delete on public.parent parent_1
8651 Foreign Delete on public.remt1 parent_2
8652 Remote SQL: DELETE FROM public.loct1 WHERE ctid = $1 RETURNING a, b
8654 Output: remt2.*, parent.tableoid, parent.ctid
8655 Join Filter: (parent.a = remt2.a)
8657 -> Seq Scan on public.parent parent_1
8658 Output: parent_1.a, parent_1.tableoid, parent_1.ctid
8659 -> Foreign Scan on public.remt1 parent_2
8660 Output: parent_2.a, parent_2.tableoid, parent_2.ctid
8661 Remote SQL: SELECT a, ctid FROM public.loct1 FOR UPDATE
8663 Output: remt2.*, remt2.a
8664 -> Foreign Scan on public.remt2
8665 Output: remt2.*, remt2.a
8666 Remote SQL: SELECT a, b FROM public.loct2
8669 delete from parent using remt2 where parent.a = remt2.a returning parent;
8677 drop foreign table remt1;
8678 drop foreign table remt2;
8682 -- ===================================================================
8683 -- test tuple routing for foreign-table partitions
8684 -- ===================================================================
8685 -- Test insert tuple routing
8686 create table itrtest (a int, b text) partition by list (a);
8687 create table loct1 (a int check (a in (1)), b text);
8688 create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1');
8689 create table loct2 (a int check (a in (2)), b text);
8690 create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2');
8691 alter table itrtest attach partition remp1 for values in (1);
8692 alter table itrtest attach partition remp2 for values in (2);
8693 insert into itrtest values (1, 'foo');
8694 insert into itrtest values (1, 'bar') returning *;
8700 insert into itrtest values (2, 'baz');
8701 insert into itrtest values (2, 'qux') returning *;
8707 insert into itrtest values (1, 'test1'), (2, 'test2') returning *;
8714 select tableoid::regclass, * FROM itrtest;
8716 ----------+---+-------
8725 select tableoid::regclass, * FROM remp1;
8727 ----------+---+-------
8733 select tableoid::regclass, * FROM remp2;
8735 ----------+-------+---
8741 delete from itrtest;
8742 -- MERGE ought to fail cleanly
8743 merge into itrtest using (select 1, 'foo') as source on (true)
8744 when matched then do nothing;
8745 ERROR: cannot execute MERGE on relation "remp1"
8746 DETAIL: This operation is not supported for foreign tables.
8747 create unique index loct1_idx on loct1 (a);
8748 -- DO NOTHING without an inference specification is supported
8749 insert into itrtest values (1, 'foo') on conflict do nothing returning *;
8755 insert into itrtest values (1, 'foo') on conflict do nothing returning *;
8760 -- But other cases are not supported
8761 insert into itrtest values (1, 'bar') on conflict (a) do nothing;
8762 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
8763 insert into itrtest values (1, 'bar') on conflict (a) do update set b = excluded.b;
8764 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
8765 select tableoid::regclass, * FROM itrtest;
8767 ----------+---+-----
8771 delete from itrtest;
8772 drop index loct1_idx;
8773 -- Test that remote triggers work with insert tuple routing
8774 create function br_insert_trigfunc() returns trigger as $$
8776 new.b := new.b || ' triggered !';
8779 $$ language plpgsql;
8780 create trigger loct1_br_insert_trigger before insert on loct1
8781 for each row execute procedure br_insert_trigfunc();
8782 create trigger loct2_br_insert_trigger before insert on loct2
8783 for each row execute procedure br_insert_trigfunc();
8784 -- The new values are concatenated with ' triggered !'
8785 insert into itrtest values (1, 'foo') returning *;
8787 ---+-----------------
8791 insert into itrtest values (2, 'qux') returning *;
8793 ---+-----------------
8797 insert into itrtest values (1, 'test1'), (2, 'test2') returning *;
8799 ---+-------------------
8800 1 | test1 triggered !
8801 2 | test2 triggered !
8804 with result as (insert into itrtest values (1, 'test1'), (2, 'test2') returning *) select * from result;
8806 ---+-------------------
8807 1 | test1 triggered !
8808 2 | test2 triggered !
8811 drop trigger loct1_br_insert_trigger on loct1;
8812 drop trigger loct2_br_insert_trigger on loct2;
8816 -- Test update tuple routing
8817 create table utrtest (a int, b text) partition by list (a);
8818 create table loct (a int check (a in (1)), b text);
8819 create foreign table remp (a int check (a in (1)), b text) server loopback options (table_name 'loct');
8820 create table locp (a int check (a in (2)), b text);
8821 alter table utrtest attach partition remp for values in (1);
8822 alter table utrtest attach partition locp for values in (2);
8823 insert into utrtest values (1, 'foo');
8824 insert into utrtest values (2, 'qux');
8825 select tableoid::regclass, * FROM utrtest;
8827 ----------+---+-----
8832 select tableoid::regclass, * FROM remp;
8834 ----------+---+-----
8838 select tableoid::regclass, * FROM locp;
8840 ----------+---+-----
8844 -- It's not allowed to move a row from a partition that is foreign to another
8845 update utrtest set a = 2 where b = 'foo' returning *;
8846 ERROR: new row for relation "loct" violates check constraint "loct_a_check"
8847 DETAIL: Failing row contains (2, foo).
8848 CONTEXT: remote SQL command: UPDATE public.loct SET a = 2 WHERE ((b = 'foo')) RETURNING a, b
8849 -- But the reverse is allowed
8850 update utrtest set a = 1 where b = 'qux' returning *;
8851 ERROR: cannot route tuples into foreign table to be updated "remp"
8852 select tableoid::regclass, * FROM utrtest;
8854 ----------+---+-----
8859 select tableoid::regclass, * FROM remp;
8861 ----------+---+-----
8865 select tableoid::regclass, * FROM locp;
8867 ----------+---+-----
8871 -- The executor should not let unexercised FDWs shut down
8872 update utrtest set a = 1 where b = 'foo';
8873 -- Test that remote triggers work with update tuple routing
8874 create trigger loct_br_insert_trigger before insert on loct
8875 for each row execute procedure br_insert_trigfunc();
8876 delete from utrtest;
8877 insert into utrtest values (2, 'qux');
8878 -- Check case where the foreign partition is a subplan target rel
8879 explain (verbose, costs off)
8880 update utrtest set a = 1 where a = 1 or a = 2 returning *;
8882 ----------------------------------------------------------------------------------------------------
8883 Update on public.utrtest
8884 Output: utrtest_1.a, utrtest_1.b
8885 Foreign Update on public.remp utrtest_1
8886 Update on public.locp utrtest_2
8888 -> Foreign Update on public.remp utrtest_1
8889 Remote SQL: UPDATE public.loct SET a = 1 WHERE (((a = 1) OR (a = 2))) RETURNING a, b
8890 -> Seq Scan on public.locp utrtest_2
8891 Output: 1, utrtest_2.tableoid, utrtest_2.ctid, NULL::record
8892 Filter: ((utrtest_2.a = 1) OR (utrtest_2.a = 2))
8895 -- The new values are concatenated with ' triggered !'
8896 update utrtest set a = 1 where a = 1 or a = 2 returning *;
8897 ERROR: cannot route tuples into foreign table to be updated "remp"
8898 delete from utrtest;
8899 insert into utrtest values (2, 'qux');
8900 -- Check case where the foreign partition isn't a subplan target rel
8901 explain (verbose, costs off)
8902 update utrtest set a = 1 where a = 2 returning *;
8904 -------------------------------------------------------
8905 Update on public.utrtest
8906 Output: utrtest_1.a, utrtest_1.b
8907 Update on public.locp utrtest_1
8908 -> Seq Scan on public.locp utrtest_1
8909 Output: 1, utrtest_1.tableoid, utrtest_1.ctid
8910 Filter: (utrtest_1.a = 2)
8913 -- The new values are concatenated with ' triggered !'
8914 update utrtest set a = 1 where a = 2 returning *;
8916 ---+-----------------
8920 drop trigger loct_br_insert_trigger on loct;
8921 -- We can move rows to a foreign partition that has been updated already,
8922 -- but can't move rows to a foreign partition that hasn't been updated yet
8923 delete from utrtest;
8924 insert into utrtest values (1, 'foo');
8925 insert into utrtest values (2, 'qux');
8926 -- Test the former case:
8927 -- with a direct modification plan
8928 explain (verbose, costs off)
8929 update utrtest set a = 1 returning *;
8931 ---------------------------------------------------------------------------
8932 Update on public.utrtest
8933 Output: utrtest_1.a, utrtest_1.b
8934 Foreign Update on public.remp utrtest_1
8935 Update on public.locp utrtest_2
8937 -> Foreign Update on public.remp utrtest_1
8938 Remote SQL: UPDATE public.loct SET a = 1 RETURNING a, b
8939 -> Seq Scan on public.locp utrtest_2
8940 Output: 1, utrtest_2.tableoid, utrtest_2.ctid, NULL::record
8943 update utrtest set a = 1 returning *;
8944 ERROR: cannot route tuples into foreign table to be updated "remp"
8945 delete from utrtest;
8946 insert into utrtest values (1, 'foo');
8947 insert into utrtest values (2, 'qux');
8948 -- with a non-direct modification plan
8949 explain (verbose, costs off)
8950 update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *;
8952 ------------------------------------------------------------------------------------------------
8953 Update on public.utrtest
8954 Output: utrtest_1.a, utrtest_1.b, "*VALUES*".column1
8955 Foreign Update on public.remp utrtest_1
8956 Remote SQL: UPDATE public.loct SET a = $2 WHERE ctid = $1 RETURNING a, b
8957 Update on public.locp utrtest_2
8959 Output: 1, "*VALUES*".*, "*VALUES*".column1, utrtest.tableoid, utrtest.ctid, utrtest.*
8960 Hash Cond: (utrtest.a = "*VALUES*".column1)
8962 -> Foreign Scan on public.remp utrtest_1
8963 Output: utrtest_1.a, utrtest_1.tableoid, utrtest_1.ctid, utrtest_1.*
8964 Remote SQL: SELECT a, b, ctid FROM public.loct FOR UPDATE
8965 -> Seq Scan on public.locp utrtest_2
8966 Output: utrtest_2.a, utrtest_2.tableoid, utrtest_2.ctid, NULL::record
8968 Output: "*VALUES*".*, "*VALUES*".column1
8969 -> Values Scan on "*VALUES*"
8970 Output: "*VALUES*".*, "*VALUES*".column1
8973 update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *;
8974 ERROR: cannot route tuples into foreign table to be updated "remp"
8975 -- Change the definition of utrtest so that the foreign partition get updated
8976 -- after the local partition
8977 delete from utrtest;
8978 alter table utrtest detach partition remp;
8979 drop foreign table remp;
8980 alter table loct drop constraint loct_a_check;
8981 alter table loct add check (a in (3));
8982 create foreign table remp (a int check (a in (3)), b text) server loopback options (table_name 'loct');
8983 alter table utrtest attach partition remp for values in (3);
8984 insert into utrtest values (2, 'qux');
8985 insert into utrtest values (3, 'xyzzy');
8986 -- Test the latter case:
8987 -- with a direct modification plan
8988 explain (verbose, costs off)
8989 update utrtest set a = 3 returning *;
8991 ---------------------------------------------------------------------------
8992 Update on public.utrtest
8993 Output: utrtest_1.a, utrtest_1.b
8994 Update on public.locp utrtest_1
8995 Foreign Update on public.remp utrtest_2
8997 -> Seq Scan on public.locp utrtest_1
8998 Output: 3, utrtest_1.tableoid, utrtest_1.ctid, NULL::record
8999 -> Foreign Update on public.remp utrtest_2
9000 Remote SQL: UPDATE public.loct SET a = 3 RETURNING a, b
9003 update utrtest set a = 3 returning *; -- ERROR
9004 ERROR: cannot route tuples into foreign table to be updated "remp"
9005 -- with a non-direct modification plan
9006 explain (verbose, costs off)
9007 update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *;
9009 -----------------------------------------------------------------------------------------------------
9010 Update on public.utrtest
9011 Output: utrtest_1.a, utrtest_1.b, "*VALUES*".column1
9012 Update on public.locp utrtest_1
9013 Foreign Update on public.remp utrtest_2
9014 Remote SQL: UPDATE public.loct SET a = $2 WHERE ctid = $1 RETURNING a, b
9016 Output: 3, "*VALUES*".*, "*VALUES*".column1, utrtest.tableoid, utrtest.ctid, (NULL::record)
9017 Hash Cond: (utrtest.a = "*VALUES*".column1)
9019 -> Seq Scan on public.locp utrtest_1
9020 Output: utrtest_1.a, utrtest_1.tableoid, utrtest_1.ctid, NULL::record
9021 -> Foreign Scan on public.remp utrtest_2
9022 Output: utrtest_2.a, utrtest_2.tableoid, utrtest_2.ctid, utrtest_2.*
9023 Remote SQL: SELECT a, b, ctid FROM public.loct FOR UPDATE
9025 Output: "*VALUES*".*, "*VALUES*".column1
9026 -> Values Scan on "*VALUES*"
9027 Output: "*VALUES*".*, "*VALUES*".column1
9030 update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; -- ERROR
9031 ERROR: cannot route tuples into foreign table to be updated "remp"
9034 -- Test copy tuple routing
9035 create table ctrtest (a int, b text) partition by list (a);
9036 create table loct1 (a int check (a in (1)), b text);
9037 create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1');
9038 create table loct2 (a int check (a in (2)), b text);
9039 create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2');
9040 alter table ctrtest attach partition remp1 for values in (1);
9041 alter table ctrtest attach partition remp2 for values in (2);
9042 copy ctrtest from stdin;
9043 select tableoid::regclass, * FROM ctrtest;
9045 ----------+---+-----
9050 select tableoid::regclass, * FROM remp1;
9052 ----------+---+-----
9056 select tableoid::regclass, * FROM remp2;
9058 ----------+-----+---
9062 -- Copying into foreign partitions directly should work as well
9063 copy remp1 from stdin;
9064 select tableoid::regclass, * FROM remp1;
9066 ----------+---+-----
9071 delete from ctrtest;
9072 -- Test copy tuple routing with the batch_size option enabled
9073 alter server loopback options (add batch_size '2');
9074 copy ctrtest from stdin;
9075 select tableoid::regclass, * FROM ctrtest;
9077 ----------+---+-------
9086 select tableoid::regclass, * FROM remp1;
9088 ----------+---+-------
9094 select tableoid::regclass, * FROM remp2;
9096 ----------+-------+---
9102 delete from ctrtest;
9103 alter server loopback options (drop batch_size);
9107 -- ===================================================================
9109 -- ===================================================================
9110 create table loc2 (f1 int, f2 text);
9111 alter table loc2 set (autovacuum_enabled = 'false');
9112 create foreign table rem2 (f1 int, f2 text) server loopback options(table_name 'loc2');
9113 -- Test basic functionality
9114 copy rem2 from stdin;
9123 -- Test check constraints
9124 alter table loc2 add constraint loc2_f1positive check (f1 >= 0);
9125 alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0);
9126 -- check constraint is enforced on the remote side, not locally
9127 copy rem2 from stdin;
9128 copy rem2 from stdin; -- ERROR
9129 ERROR: new row for relation "loc2" violates check constraint "loc2_f1positive"
9130 DETAIL: Failing row contains (-1, xyzzy).
9131 CONTEXT: remote SQL command: INSERT INTO public.loc2(f1, f2) VALUES ($1, $2)
9132 COPY rem2, line 1: "-1 xyzzy"
9140 alter foreign table rem2 drop constraint rem2_f1positive;
9141 alter table loc2 drop constraint loc2_f1positive;
9143 -- Test local triggers
9144 create trigger trig_stmt_before before insert on rem2
9145 for each statement execute procedure trigger_func();
9146 create trigger trig_stmt_after after insert on rem2
9147 for each statement execute procedure trigger_func();
9148 create trigger trig_row_before before insert on rem2
9149 for each row execute procedure trigger_data(23,'skidoo');
9150 create trigger trig_row_after after insert on rem2
9151 for each row execute procedure trigger_data(23,'skidoo');
9152 copy rem2 from stdin;
9153 NOTICE: trigger_func(<NULL>) called: action = INSERT, when = BEFORE, level = STATEMENT
9154 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem2
9155 NOTICE: NEW: (1,foo)
9156 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem2
9157 NOTICE: NEW: (2,bar)
9158 NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem2
9159 NOTICE: NEW: (1,foo)
9160 NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem2
9161 NOTICE: NEW: (2,bar)
9162 NOTICE: trigger_func(<NULL>) called: action = INSERT, when = AFTER, level = STATEMENT
9170 drop trigger trig_row_before on rem2;
9171 drop trigger trig_row_after on rem2;
9172 drop trigger trig_stmt_before on rem2;
9173 drop trigger trig_stmt_after on rem2;
9175 create trigger trig_row_before_insert before insert on rem2
9176 for each row execute procedure trig_row_before_insupdate();
9177 -- The new values are concatenated with ' triggered !'
9178 copy rem2 from stdin;
9181 ----+-----------------
9186 drop trigger trig_row_before_insert on rem2;
9188 create trigger trig_null before insert on rem2
9189 for each row execute procedure trig_null();
9191 copy rem2 from stdin;
9197 drop trigger trig_null on rem2;
9199 -- Test remote triggers
9200 create trigger trig_row_before_insert before insert on loc2
9201 for each row execute procedure trig_row_before_insupdate();
9202 -- The new values are concatenated with ' triggered !'
9203 copy rem2 from stdin;
9206 ----+-----------------
9211 drop trigger trig_row_before_insert on loc2;
9213 create trigger trig_null before insert on loc2
9214 for each row execute procedure trig_null();
9216 copy rem2 from stdin;
9222 drop trigger trig_null on loc2;
9224 -- Test a combination of local and remote triggers
9225 create trigger rem2_trig_row_before before insert on rem2
9226 for each row execute procedure trigger_data(23,'skidoo');
9227 create trigger rem2_trig_row_after after insert on rem2
9228 for each row execute procedure trigger_data(23,'skidoo');
9229 create trigger loc2_trig_row_before_insert before insert on loc2
9230 for each row execute procedure trig_row_before_insupdate();
9231 copy rem2 from stdin;
9232 NOTICE: rem2_trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem2
9233 NOTICE: NEW: (1,foo)
9234 NOTICE: rem2_trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem2
9235 NOTICE: NEW: (2,bar)
9236 NOTICE: rem2_trig_row_after(23, skidoo) AFTER ROW INSERT ON rem2
9237 NOTICE: NEW: (1,"foo triggered !")
9238 NOTICE: rem2_trig_row_after(23, skidoo) AFTER ROW INSERT ON rem2
9239 NOTICE: NEW: (2,"bar triggered !")
9242 ----+-----------------
9247 drop trigger rem2_trig_row_before on rem2;
9248 drop trigger rem2_trig_row_after on rem2;
9249 drop trigger loc2_trig_row_before_insert on loc2;
9251 -- test COPY FROM with foreign table created in the same transaction
9252 create table loc3 (f1 int, f2 text);
9254 create foreign table rem3 (f1 int, f2 text)
9255 server loopback options(table_name 'loc3');
9256 copy rem3 from stdin;
9265 drop foreign table rem3;
9267 -- Test COPY FROM with the batch_size option enabled
9268 alter server loopback options (add batch_size '2');
9269 -- Test basic functionality
9270 copy rem2 from stdin;
9280 -- Test check constraints
9281 alter table loc2 add constraint loc2_f1positive check (f1 >= 0);
9282 alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0);
9283 -- check constraint is enforced on the remote side, not locally
9284 copy rem2 from stdin;
9285 copy rem2 from stdin; -- ERROR
9286 ERROR: new row for relation "loc2" violates check constraint "loc2_f1positive"
9287 DETAIL: Failing row contains (-1, xyzzy).
9288 CONTEXT: remote SQL command: INSERT INTO public.loc2(f1, f2) VALUES ($1, $2)
9298 alter foreign table rem2 drop constraint rem2_f1positive;
9299 alter table loc2 drop constraint loc2_f1positive;
9301 -- Test remote triggers
9302 create trigger trig_row_before_insert before insert on loc2
9303 for each row execute procedure trig_row_before_insupdate();
9304 -- The new values are concatenated with ' triggered !'
9305 copy rem2 from stdin;
9308 ----+-----------------
9314 drop trigger trig_row_before_insert on loc2;
9316 create trigger trig_null before insert on loc2
9317 for each row execute procedure trig_null();
9319 copy rem2 from stdin;
9325 drop trigger trig_null on loc2;
9327 -- Check with zero-column foreign table; batch insert will be disabled
9328 alter table loc2 drop column f1;
9329 alter table loc2 drop column f2;
9330 alter table rem2 drop column f1;
9331 alter table rem2 drop column f2;
9332 copy rem2 from stdin;
9338 alter server loopback options (drop batch_size);
9339 -- ===================================================================
9340 -- test for TRUNCATE
9341 -- ===================================================================
9342 CREATE TABLE tru_rtable0 (id int primary key);
9343 CREATE FOREIGN TABLE tru_ftable (id int)
9344 SERVER loopback OPTIONS (table_name 'tru_rtable0');
9345 INSERT INTO tru_rtable0 (SELECT x FROM generate_series(1,10) x);
9346 CREATE TABLE tru_ptable (id int) PARTITION BY HASH(id);
9347 CREATE TABLE tru_ptable__p0 PARTITION OF tru_ptable
9348 FOR VALUES WITH (MODULUS 2, REMAINDER 0);
9349 CREATE TABLE tru_rtable1 (id int primary key);
9350 CREATE FOREIGN TABLE tru_ftable__p1 PARTITION OF tru_ptable
9351 FOR VALUES WITH (MODULUS 2, REMAINDER 1)
9352 SERVER loopback OPTIONS (table_name 'tru_rtable1');
9353 INSERT INTO tru_ptable (SELECT x FROM generate_series(11,20) x);
9354 CREATE TABLE tru_pk_table(id int primary key);
9355 CREATE TABLE tru_fk_table(fkey int references tru_pk_table(id));
9356 INSERT INTO tru_pk_table (SELECT x FROM generate_series(1,10) x);
9357 INSERT INTO tru_fk_table (SELECT x % 10 + 1 FROM generate_series(5,25) x);
9358 CREATE FOREIGN TABLE tru_pk_ftable (id int)
9359 SERVER loopback OPTIONS (table_name 'tru_pk_table');
9360 CREATE TABLE tru_rtable_parent (id int);
9361 CREATE TABLE tru_rtable_child (id int);
9362 CREATE FOREIGN TABLE tru_ftable_parent (id int)
9363 SERVER loopback OPTIONS (table_name 'tru_rtable_parent');
9364 CREATE FOREIGN TABLE tru_ftable_child () INHERITS (tru_ftable_parent)
9365 SERVER loopback OPTIONS (table_name 'tru_rtable_child');
9366 INSERT INTO tru_rtable_parent (SELECT x FROM generate_series(1,8) x);
9367 INSERT INTO tru_rtable_child (SELECT x FROM generate_series(10, 18) x);
9369 SELECT sum(id) FROM tru_ftable; -- 55
9375 TRUNCATE tru_ftable;
9376 SELECT count(*) FROM tru_rtable0; -- 0
9382 SELECT count(*) FROM tru_ftable; -- 0
9388 -- 'truncatable' option
9389 ALTER SERVER loopback OPTIONS (ADD truncatable 'false');
9390 TRUNCATE tru_ftable; -- error
9391 ERROR: foreign table "tru_ftable" does not allow truncates
9392 ALTER FOREIGN TABLE tru_ftable OPTIONS (ADD truncatable 'true');
9393 TRUNCATE tru_ftable; -- accepted
9394 ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'false');
9395 TRUNCATE tru_ftable; -- error
9396 ERROR: foreign table "tru_ftable" does not allow truncates
9397 ALTER SERVER loopback OPTIONS (DROP truncatable);
9398 ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'false');
9399 TRUNCATE tru_ftable; -- error
9400 ERROR: foreign table "tru_ftable" does not allow truncates
9401 ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'true');
9402 TRUNCATE tru_ftable; -- accepted
9403 -- partitioned table with both local and foreign tables as partitions
9404 SELECT sum(id) FROM tru_ptable; -- 155
9410 TRUNCATE tru_ptable;
9411 SELECT count(*) FROM tru_ptable; -- 0
9417 SELECT count(*) FROM tru_ptable__p0; -- 0
9423 SELECT count(*) FROM tru_ftable__p1; -- 0
9429 SELECT count(*) FROM tru_rtable1; -- 0
9436 SELECT sum(id) FROM tru_pk_ftable; -- 55
9442 TRUNCATE tru_pk_ftable; -- failed by FK reference
9443 ERROR: cannot truncate a table referenced in a foreign key constraint
9444 DETAIL: Table "tru_fk_table" references "tru_pk_table".
9445 HINT: Truncate table "tru_fk_table" at the same time, or use TRUNCATE ... CASCADE.
9446 CONTEXT: remote SQL command: TRUNCATE public.tru_pk_table CONTINUE IDENTITY RESTRICT
9447 TRUNCATE tru_pk_ftable CASCADE;
9448 SELECT count(*) FROM tru_pk_ftable; -- 0
9454 SELECT count(*) FROM tru_fk_table; -- also truncated,0
9460 -- truncate two tables at a command
9461 INSERT INTO tru_ftable (SELECT x FROM generate_series(1,8) x);
9462 INSERT INTO tru_pk_ftable (SELECT x FROM generate_series(3,10) x);
9463 SELECT count(*) from tru_ftable; -- 8
9469 SELECT count(*) from tru_pk_ftable; -- 8
9475 TRUNCATE tru_ftable, tru_pk_ftable CASCADE;
9476 SELECT count(*) from tru_ftable; -- 0
9482 SELECT count(*) from tru_pk_ftable; -- 0
9488 -- truncate with ONLY clause
9489 -- Since ONLY is specified, the table tru_ftable_child that inherits
9490 -- tru_ftable_parent locally is not truncated.
9491 TRUNCATE ONLY tru_ftable_parent;
9492 SELECT sum(id) FROM tru_ftable_parent; -- 126
9498 TRUNCATE tru_ftable_parent;
9499 SELECT count(*) FROM tru_ftable_parent; -- 0
9505 -- in case when remote table has inherited children
9506 CREATE TABLE tru_rtable0_child () INHERITS (tru_rtable0);
9507 INSERT INTO tru_rtable0 (SELECT x FROM generate_series(5,9) x);
9508 INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(10,14) x);
9509 SELECT sum(id) FROM tru_ftable; -- 95
9515 -- Both parent and child tables in the foreign server are truncated
9516 -- even though ONLY is specified because ONLY has no effect
9517 -- when truncating a foreign table.
9518 TRUNCATE ONLY tru_ftable;
9519 SELECT count(*) FROM tru_ftable; -- 0
9525 INSERT INTO tru_rtable0 (SELECT x FROM generate_series(21,25) x);
9526 INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(26,30) x);
9527 SELECT sum(id) FROM tru_ftable; -- 255
9533 TRUNCATE tru_ftable; -- truncate both of parent and child
9534 SELECT count(*) FROM tru_ftable; -- 0
9541 DROP FOREIGN TABLE tru_ftable_parent, tru_ftable_child, tru_pk_ftable,tru_ftable__p1,tru_ftable;
9542 DROP TABLE tru_rtable0, tru_rtable1, tru_ptable, tru_ptable__p0, tru_pk_table, tru_fk_table,
9543 tru_rtable_parent,tru_rtable_child, tru_rtable0_child;
9544 -- ===================================================================
9545 -- test IMPORT FOREIGN SCHEMA
9546 -- ===================================================================
9547 CREATE SCHEMA import_source;
9548 CREATE TABLE import_source.t1 (c1 int, c2 varchar NOT NULL);
9549 CREATE TABLE import_source.t2 (c1 int default 42, c2 varchar NULL, c3 text collate "POSIX");
9550 CREATE TYPE typ1 AS (m1 int, m2 varchar);
9551 CREATE TABLE import_source.t3 (c1 timestamptz default now(), c2 typ1);
9552 CREATE TABLE import_source."x 4" (c1 float8, "C 2" text, c3 varchar(42));
9553 CREATE TABLE import_source."x 5" (c1 float8);
9554 ALTER TABLE import_source."x 5" DROP COLUMN c1;
9555 CREATE TABLE import_source."x 6" (c1 int, c2 int generated always as (c1 * 2) stored);
9556 CREATE TABLE import_source.t4 (c1 int) PARTITION BY RANGE (c1);
9557 CREATE TABLE import_source.t4_part PARTITION OF import_source.t4
9558 FOR VALUES FROM (1) TO (100);
9559 CREATE TABLE import_source.t4_part2 PARTITION OF import_source.t4
9560 FOR VALUES FROM (100) TO (200);
9561 CREATE SCHEMA import_dest1;
9562 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest1;
9563 \det+ import_dest1.*
9564 List of foreign tables
9565 Schema | Table | Server | FDW options | Description
9566 --------------+-------+----------+-------------------------------------------------+-------------
9567 import_dest1 | t1 | loopback | (schema_name 'import_source', table_name 't1') |
9568 import_dest1 | t2 | loopback | (schema_name 'import_source', table_name 't2') |
9569 import_dest1 | t3 | loopback | (schema_name 'import_source', table_name 't3') |
9570 import_dest1 | t4 | loopback | (schema_name 'import_source', table_name 't4') |
9571 import_dest1 | x 4 | loopback | (schema_name 'import_source', table_name 'x 4') |
9572 import_dest1 | x 5 | loopback | (schema_name 'import_source', table_name 'x 5') |
9573 import_dest1 | x 6 | loopback | (schema_name 'import_source', table_name 'x 6') |
9577 Foreign table "import_dest1.t1"
9578 Column | Type | Collation | Nullable | Default | FDW options
9579 --------+-------------------+-----------+----------+---------+--------------------
9580 c1 | integer | | | | (column_name 'c1')
9581 c2 | character varying | | not null | | (column_name 'c2')
9583 FDW options: (schema_name 'import_source', table_name 't1')
9585 Foreign table "import_dest1.t2"
9586 Column | Type | Collation | Nullable | Default | FDW options
9587 --------+-------------------+-----------+----------+---------+--------------------
9588 c1 | integer | | | | (column_name 'c1')
9589 c2 | character varying | | | | (column_name 'c2')
9590 c3 | text | POSIX | | | (column_name 'c3')
9592 FDW options: (schema_name 'import_source', table_name 't2')
9594 Foreign table "import_dest1.t3"
9595 Column | Type | Collation | Nullable | Default | FDW options
9596 --------+--------------------------+-----------+----------+---------+--------------------
9597 c1 | timestamp with time zone | | | | (column_name 'c1')
9598 c2 | typ1 | | | | (column_name 'c2')
9600 FDW options: (schema_name 'import_source', table_name 't3')
9602 Foreign table "import_dest1.t4"
9603 Column | Type | Collation | Nullable | Default | FDW options
9604 --------+---------+-----------+----------+---------+--------------------
9605 c1 | integer | | | | (column_name 'c1')
9607 FDW options: (schema_name 'import_source', table_name 't4')
9609 Foreign table "import_dest1.x 4"
9610 Column | Type | Collation | Nullable | Default | FDW options
9611 --------+-----------------------+-----------+----------+---------+---------------------
9612 c1 | double precision | | | | (column_name 'c1')
9613 C 2 | text | | | | (column_name 'C 2')
9614 c3 | character varying(42) | | | | (column_name 'c3')
9616 FDW options: (schema_name 'import_source', table_name 'x 4')
9618 Foreign table "import_dest1.x 5"
9619 Column | Type | Collation | Nullable | Default | FDW options
9620 --------+------+-----------+----------+---------+-------------
9622 FDW options: (schema_name 'import_source', table_name 'x 5')
9624 Foreign table "import_dest1.x 6"
9625 Column | Type | Collation | Nullable | Default | FDW options
9626 --------+---------+-----------+----------+-------------------------------------+--------------------
9627 c1 | integer | | | | (column_name 'c1')
9628 c2 | integer | | | generated always as (c1 * 2) stored | (column_name 'c2')
9630 FDW options: (schema_name 'import_source', table_name 'x 6')
9633 CREATE SCHEMA import_dest2;
9634 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest2
9635 OPTIONS (import_default 'true');
9636 \det+ import_dest2.*
9637 List of foreign tables
9638 Schema | Table | Server | FDW options | Description
9639 --------------+-------+----------+-------------------------------------------------+-------------
9640 import_dest2 | t1 | loopback | (schema_name 'import_source', table_name 't1') |
9641 import_dest2 | t2 | loopback | (schema_name 'import_source', table_name 't2') |
9642 import_dest2 | t3 | loopback | (schema_name 'import_source', table_name 't3') |
9643 import_dest2 | t4 | loopback | (schema_name 'import_source', table_name 't4') |
9644 import_dest2 | x 4 | loopback | (schema_name 'import_source', table_name 'x 4') |
9645 import_dest2 | x 5 | loopback | (schema_name 'import_source', table_name 'x 5') |
9646 import_dest2 | x 6 | loopback | (schema_name 'import_source', table_name 'x 6') |
9650 Foreign table "import_dest2.t1"
9651 Column | Type | Collation | Nullable | Default | FDW options
9652 --------+-------------------+-----------+----------+---------+--------------------
9653 c1 | integer | | | | (column_name 'c1')
9654 c2 | character varying | | not null | | (column_name 'c2')
9656 FDW options: (schema_name 'import_source', table_name 't1')
9658 Foreign table "import_dest2.t2"
9659 Column | Type | Collation | Nullable | Default | FDW options
9660 --------+-------------------+-----------+----------+---------+--------------------
9661 c1 | integer | | | 42 | (column_name 'c1')
9662 c2 | character varying | | | | (column_name 'c2')
9663 c3 | text | POSIX | | | (column_name 'c3')
9665 FDW options: (schema_name 'import_source', table_name 't2')
9667 Foreign table "import_dest2.t3"
9668 Column | Type | Collation | Nullable | Default | FDW options
9669 --------+--------------------------+-----------+----------+---------+--------------------
9670 c1 | timestamp with time zone | | | now() | (column_name 'c1')
9671 c2 | typ1 | | | | (column_name 'c2')
9673 FDW options: (schema_name 'import_source', table_name 't3')
9675 Foreign table "import_dest2.t4"
9676 Column | Type | Collation | Nullable | Default | FDW options
9677 --------+---------+-----------+----------+---------+--------------------
9678 c1 | integer | | | | (column_name 'c1')
9680 FDW options: (schema_name 'import_source', table_name 't4')
9682 Foreign table "import_dest2.x 4"
9683 Column | Type | Collation | Nullable | Default | FDW options
9684 --------+-----------------------+-----------+----------+---------+---------------------
9685 c1 | double precision | | | | (column_name 'c1')
9686 C 2 | text | | | | (column_name 'C 2')
9687 c3 | character varying(42) | | | | (column_name 'c3')
9689 FDW options: (schema_name 'import_source', table_name 'x 4')
9691 Foreign table "import_dest2.x 5"
9692 Column | Type | Collation | Nullable | Default | FDW options
9693 --------+------+-----------+----------+---------+-------------
9695 FDW options: (schema_name 'import_source', table_name 'x 5')
9697 Foreign table "import_dest2.x 6"
9698 Column | Type | Collation | Nullable | Default | FDW options
9699 --------+---------+-----------+----------+-------------------------------------+--------------------
9700 c1 | integer | | | | (column_name 'c1')
9701 c2 | integer | | | generated always as (c1 * 2) stored | (column_name 'c2')
9703 FDW options: (schema_name 'import_source', table_name 'x 6')
9705 CREATE SCHEMA import_dest3;
9706 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest3
9707 OPTIONS (import_collate 'false', import_generated 'false', import_not_null 'false');
9708 \det+ import_dest3.*
9709 List of foreign tables
9710 Schema | Table | Server | FDW options | Description
9711 --------------+-------+----------+-------------------------------------------------+-------------
9712 import_dest3 | t1 | loopback | (schema_name 'import_source', table_name 't1') |
9713 import_dest3 | t2 | loopback | (schema_name 'import_source', table_name 't2') |
9714 import_dest3 | t3 | loopback | (schema_name 'import_source', table_name 't3') |
9715 import_dest3 | t4 | loopback | (schema_name 'import_source', table_name 't4') |
9716 import_dest3 | x 4 | loopback | (schema_name 'import_source', table_name 'x 4') |
9717 import_dest3 | x 5 | loopback | (schema_name 'import_source', table_name 'x 5') |
9718 import_dest3 | x 6 | loopback | (schema_name 'import_source', table_name 'x 6') |
9722 Foreign table "import_dest3.t1"
9723 Column | Type | Collation | Nullable | Default | FDW options
9724 --------+-------------------+-----------+----------+---------+--------------------
9725 c1 | integer | | | | (column_name 'c1')
9726 c2 | character varying | | | | (column_name 'c2')
9728 FDW options: (schema_name 'import_source', table_name 't1')
9730 Foreign table "import_dest3.t2"
9731 Column | Type | Collation | Nullable | Default | FDW options
9732 --------+-------------------+-----------+----------+---------+--------------------
9733 c1 | integer | | | | (column_name 'c1')
9734 c2 | character varying | | | | (column_name 'c2')
9735 c3 | text | | | | (column_name 'c3')
9737 FDW options: (schema_name 'import_source', table_name 't2')
9739 Foreign table "import_dest3.t3"
9740 Column | Type | Collation | Nullable | Default | FDW options
9741 --------+--------------------------+-----------+----------+---------+--------------------
9742 c1 | timestamp with time zone | | | | (column_name 'c1')
9743 c2 | typ1 | | | | (column_name 'c2')
9745 FDW options: (schema_name 'import_source', table_name 't3')
9747 Foreign table "import_dest3.t4"
9748 Column | Type | Collation | Nullable | Default | FDW options
9749 --------+---------+-----------+----------+---------+--------------------
9750 c1 | integer | | | | (column_name 'c1')
9752 FDW options: (schema_name 'import_source', table_name 't4')
9754 Foreign table "import_dest3.x 4"
9755 Column | Type | Collation | Nullable | Default | FDW options
9756 --------+-----------------------+-----------+----------+---------+---------------------
9757 c1 | double precision | | | | (column_name 'c1')
9758 C 2 | text | | | | (column_name 'C 2')
9759 c3 | character varying(42) | | | | (column_name 'c3')
9761 FDW options: (schema_name 'import_source', table_name 'x 4')
9763 Foreign table "import_dest3.x 5"
9764 Column | Type | Collation | Nullable | Default | FDW options
9765 --------+------+-----------+----------+---------+-------------
9767 FDW options: (schema_name 'import_source', table_name 'x 5')
9769 Foreign table "import_dest3.x 6"
9770 Column | Type | Collation | Nullable | Default | FDW options
9771 --------+---------+-----------+----------+---------+--------------------
9772 c1 | integer | | | | (column_name 'c1')
9773 c2 | integer | | | | (column_name 'c2')
9775 FDW options: (schema_name 'import_source', table_name 'x 6')
9777 -- Check LIMIT TO and EXCEPT
9778 CREATE SCHEMA import_dest4;
9779 IMPORT FOREIGN SCHEMA import_source LIMIT TO (t1, nonesuch, t4_part)
9780 FROM SERVER loopback INTO import_dest4;
9781 \det+ import_dest4.*
9782 List of foreign tables
9783 Schema | Table | Server | FDW options | Description
9784 --------------+---------+----------+-----------------------------------------------------+-------------
9785 import_dest4 | t1 | loopback | (schema_name 'import_source', table_name 't1') |
9786 import_dest4 | t4_part | loopback | (schema_name 'import_source', table_name 't4_part') |
9789 IMPORT FOREIGN SCHEMA import_source EXCEPT (t1, "x 4", nonesuch, t4_part)
9790 FROM SERVER loopback INTO import_dest4;
9791 \det+ import_dest4.*
9792 List of foreign tables
9793 Schema | Table | Server | FDW options | Description
9794 --------------+---------+----------+-----------------------------------------------------+-------------
9795 import_dest4 | t1 | loopback | (schema_name 'import_source', table_name 't1') |
9796 import_dest4 | t2 | loopback | (schema_name 'import_source', table_name 't2') |
9797 import_dest4 | t3 | loopback | (schema_name 'import_source', table_name 't3') |
9798 import_dest4 | t4 | loopback | (schema_name 'import_source', table_name 't4') |
9799 import_dest4 | t4_part | loopback | (schema_name 'import_source', table_name 't4_part') |
9800 import_dest4 | x 5 | loopback | (schema_name 'import_source', table_name 'x 5') |
9801 import_dest4 | x 6 | loopback | (schema_name 'import_source', table_name 'x 6') |
9804 -- Assorted error cases
9805 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest4;
9806 ERROR: relation "t1" already exists
9807 CONTEXT: importing foreign table "t1"
9808 IMPORT FOREIGN SCHEMA nonesuch FROM SERVER loopback INTO import_dest4;
9809 ERROR: schema "nonesuch" is not present on foreign server "loopback"
9810 IMPORT FOREIGN SCHEMA nonesuch FROM SERVER loopback INTO notthere;
9811 ERROR: schema "notthere" does not exist
9812 IMPORT FOREIGN SCHEMA nonesuch FROM SERVER nowhere INTO notthere;
9813 ERROR: server "nowhere" does not exist
9814 -- Check case of a type present only on the remote server.
9815 -- We can fake this by dropping the type locally in our transaction.
9816 CREATE TYPE "Colors" AS ENUM ('red', 'green', 'blue');
9817 CREATE TABLE import_source.t5 (c1 int, c2 text collate "C", "Col" "Colors");
9818 CREATE SCHEMA import_dest5;
9820 DROP TYPE "Colors" CASCADE;
9821 NOTICE: drop cascades to column Col of table import_source.t5
9822 IMPORT FOREIGN SCHEMA import_source LIMIT TO (t5)
9823 FROM SERVER loopback INTO import_dest5; -- ERROR
9824 ERROR: type "public.Colors" does not exist
9825 LINE 4: "Col" public."Colors" OPTIONS (column_name 'Col')
9827 QUERY: CREATE FOREIGN TABLE t5 (
9828 c1 integer OPTIONS (column_name 'c1'),
9829 c2 text OPTIONS (column_name 'c2') COLLATE pg_catalog."C",
9830 "Col" public."Colors" OPTIONS (column_name 'Col')
9832 OPTIONS (schema_name 'import_source', table_name 't5');
9833 CONTEXT: importing foreign table "t5"
9836 CREATE SERVER fetch101 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( fetch_size '101' );
9838 FROM pg_foreign_server
9839 WHERE srvname = 'fetch101'
9840 AND srvoptions @> array['fetch_size=101'];
9846 ALTER SERVER fetch101 OPTIONS( SET fetch_size '202' );
9848 FROM pg_foreign_server
9849 WHERE srvname = 'fetch101'
9850 AND srvoptions @> array['fetch_size=101'];
9857 FROM pg_foreign_server
9858 WHERE srvname = 'fetch101'
9859 AND srvoptions @> array['fetch_size=202'];
9865 CREATE FOREIGN TABLE table30000 ( x int ) SERVER fetch101 OPTIONS ( fetch_size '30000' );
9867 FROM pg_foreign_table
9868 WHERE ftrelid = 'table30000'::regclass
9869 AND ftoptions @> array['fetch_size=30000'];
9875 ALTER FOREIGN TABLE table30000 OPTIONS ( SET fetch_size '60000');
9877 FROM pg_foreign_table
9878 WHERE ftrelid = 'table30000'::regclass
9879 AND ftoptions @> array['fetch_size=30000'];
9886 FROM pg_foreign_table
9887 WHERE ftrelid = 'table30000'::regclass
9888 AND ftoptions @> array['fetch_size=60000'];
9895 -- ===================================================================
9896 -- test partitionwise joins
9897 -- ===================================================================
9898 SET enable_partitionwise_join=on;
9899 CREATE TABLE fprt1 (a int, b int, c varchar) PARTITION BY RANGE(a);
9900 CREATE TABLE fprt1_p1 (LIKE fprt1);
9901 CREATE TABLE fprt1_p2 (LIKE fprt1);
9902 ALTER TABLE fprt1_p1 SET (autovacuum_enabled = 'false');
9903 ALTER TABLE fprt1_p2 SET (autovacuum_enabled = 'false');
9904 INSERT INTO fprt1_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 2) i;
9905 INSERT INTO fprt1_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 2) i;
9906 CREATE FOREIGN TABLE ftprt1_p1 PARTITION OF fprt1 FOR VALUES FROM (0) TO (250)
9907 SERVER loopback OPTIONS (table_name 'fprt1_p1', use_remote_estimate 'true');
9908 CREATE FOREIGN TABLE ftprt1_p2 PARTITION OF fprt1 FOR VALUES FROM (250) TO (500)
9909 SERVER loopback OPTIONS (TABLE_NAME 'fprt1_p2');
9913 CREATE TABLE fprt2 (a int, b int, c varchar) PARTITION BY RANGE(b);
9914 CREATE TABLE fprt2_p1 (LIKE fprt2);
9915 CREATE TABLE fprt2_p2 (LIKE fprt2);
9916 ALTER TABLE fprt2_p1 SET (autovacuum_enabled = 'false');
9917 ALTER TABLE fprt2_p2 SET (autovacuum_enabled = 'false');
9918 INSERT INTO fprt2_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 3) i;
9919 INSERT INTO fprt2_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 3) i;
9920 CREATE FOREIGN TABLE ftprt2_p1 (b int, c varchar, a int)
9921 SERVER loopback OPTIONS (table_name 'fprt2_p1', use_remote_estimate 'true');
9922 ALTER TABLE fprt2 ATTACH PARTITION ftprt2_p1 FOR VALUES FROM (0) TO (250);
9923 CREATE FOREIGN TABLE ftprt2_p2 PARTITION OF fprt2 FOR VALUES FROM (250) TO (500)
9924 SERVER loopback OPTIONS (table_name 'fprt2_p2', use_remote_estimate 'true');
9928 -- inner join three tables
9930 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;
9932 -----------------------------------------------------------------------------------------------------
9934 Sort Key: t1.a, t3.c
9937 Relations: ((ftprt1_p1 t1_1) INNER JOIN (ftprt2_p1 t2_1)) INNER JOIN (ftprt1_p1 t3_1)
9939 Relations: ((ftprt1_p2 t1_2) INNER JOIN (ftprt2_p2 t2_2)) INNER JOIN (ftprt1_p2 t3_2)
9942 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;
9951 -- left outer join + nullable clause
9952 EXPLAIN (VERBOSE, COSTS OFF)
9953 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;
9955 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
9957 Output: t1.a, fprt2.b, fprt2.c
9958 Relations: (public.ftprt1_p1 t1) LEFT JOIN (public.ftprt2_p1 fprt2)
9959 Remote SQL: SELECT r5.a, r6.b, r6.c FROM (public.fprt1_p1 r5 LEFT JOIN public.fprt2_p1 r6 ON (((r5.a = r6.b)) AND ((r5.b = r6.a)) AND ((r6.a < 10)))) WHERE ((r5.a < 10)) ORDER BY r5.a ASC NULLS LAST, r6.b ASC NULLS LAST, r6.c ASC NULLS LAST
9962 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;
9972 -- with whole-row reference; partitionwise join does not apply
9974 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;
9976 --------------------------------------------------------
9978 Sort Key: ((t1.*)::fprt1), ((t2.*)::fprt2)
9980 Hash Cond: (t1.a = t2.b)
9982 -> Foreign Scan on ftprt1_p1 t1_1
9983 -> Foreign Scan on ftprt1_p2 t1_2
9986 -> Foreign Scan on ftprt2_p1 t2_1
9987 -> Foreign Scan on ftprt2_p2 t2_2
9990 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;
9992 ----------------+----------------
9993 (0,0,0000) | (0,0,0000)
9996 (150,150,0003) | (150,150,0003)
9998 (250,250,0005) | (250,250,0005)
10001 (400,400,0008) | (400,400,0008)
10009 -- join with lateral reference
10010 EXPLAIN (COSTS OFF)
10011 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;
10013 -----------------------------------------------------------------------
10015 Sort Key: t1.a, t1.b
10018 Relations: (ftprt1_p1 t1_1) INNER JOIN (ftprt2_p1 t2_1)
10020 Relations: (ftprt1_p2 t1_2) INNER JOIN (ftprt2_p2 t2_2)
10023 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;
10032 -- with PHVs, partitionwise join selected but no join pushdown
10033 EXPLAIN (COSTS OFF)
10034 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;
10036 -----------------------------------------------------------
10038 Sort Key: fprt1.a, fprt2.b
10041 Hash Cond: (fprt1_1.a = fprt2_1.b)
10042 -> Foreign Scan on ftprt1_p1 fprt1_1
10044 -> Foreign Scan on ftprt2_p1 fprt2_1
10046 Hash Cond: (fprt1_2.a = fprt2_2.b)
10047 -> Foreign Scan on ftprt1_p2 fprt1_2
10049 -> Foreign Scan on ftprt2_p2 fprt2_2
10052 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;
10054 -----+--------+-----+--------
10055 0 | t1_phv | 0 | t2_phv
10058 150 | t1_phv | 150 | t2_phv
10060 250 | t1_phv | 250 | t2_phv
10063 400 | t1_phv | 400 | t2_phv
10071 -- test FOR UPDATE; partitionwise join does not apply
10072 EXPLAIN (COSTS OFF)
10073 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;
10075 --------------------------------------------------------
10078 Join Filter: (t1.a = t2.b)
10080 -> Foreign Scan on ftprt1_p1 t1_1
10081 -> Foreign Scan on ftprt1_p2 t1_2
10084 -> Foreign Scan on ftprt2_p1 t2_1
10085 -> Foreign Scan on ftprt2_p2 t2_2
10088 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;
10097 RESET enable_partitionwise_join;
10098 -- ===================================================================
10099 -- test partitionwise aggregates
10100 -- ===================================================================
10101 CREATE TABLE pagg_tab (a int, b int, c text) PARTITION BY RANGE(a);
10102 CREATE TABLE pagg_tab_p1 (LIKE pagg_tab);
10103 CREATE TABLE pagg_tab_p2 (LIKE pagg_tab);
10104 CREATE TABLE pagg_tab_p3 (LIKE pagg_tab);
10105 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;
10106 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;
10107 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;
10108 -- Create foreign partitions
10109 CREATE FOREIGN TABLE fpagg_tab_p1 PARTITION OF pagg_tab FOR VALUES FROM (0) TO (10) SERVER loopback OPTIONS (table_name 'pagg_tab_p1');
10110 CREATE FOREIGN TABLE fpagg_tab_p2 PARTITION OF pagg_tab FOR VALUES FROM (10) TO (20) SERVER loopback OPTIONS (table_name 'pagg_tab_p2');
10111 CREATE FOREIGN TABLE fpagg_tab_p3 PARTITION OF pagg_tab FOR VALUES FROM (20) TO (30) SERVER loopback OPTIONS (table_name 'pagg_tab_p3');
10113 ANALYZE fpagg_tab_p1;
10114 ANALYZE fpagg_tab_p2;
10115 ANALYZE fpagg_tab_p3;
10116 -- When GROUP BY clause matches with PARTITION KEY.
10117 -- Plan with partitionwise aggregates is disabled
10118 SET enable_partitionwise_aggregate TO false;
10119 EXPLAIN (COSTS OFF)
10120 SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1;
10122 -----------------------------------------------------
10124 Group Key: pagg_tab.a
10125 Filter: (avg(pagg_tab.b) < '22'::numeric)
10127 -> Foreign Scan on fpagg_tab_p1 pagg_tab_1
10128 -> Foreign Scan on fpagg_tab_p2 pagg_tab_2
10129 -> Foreign Scan on fpagg_tab_p3 pagg_tab_3
10132 -- Plan with partitionwise aggregates is enabled
10133 SET enable_partitionwise_aggregate TO true;
10134 EXPLAIN (COSTS OFF)
10135 SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1;
10137 -----------------------------------------------------------------
10139 Sort Key: pagg_tab.a
10142 Relations: Aggregate on (fpagg_tab_p1 pagg_tab)
10144 Relations: Aggregate on (fpagg_tab_p2 pagg_tab_1)
10146 Relations: Aggregate on (fpagg_tab_p3 pagg_tab_2)
10149 SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1;
10150 a | sum | min | count
10151 ----+------+-----+-------
10154 10 | 2000 | 0 | 100
10155 11 | 2100 | 1 | 100
10156 20 | 2000 | 0 | 100
10157 21 | 2100 | 1 | 100
10160 -- Check with whole-row reference
10161 -- Should have all the columns in the target list for the given relation
10162 EXPLAIN (VERBOSE, COSTS OFF)
10163 SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1;
10165 --------------------------------------------------------------------------------------------
10169 Output: t1.a, count(((t1.*)::pagg_tab))
10171 Filter: (avg(t1.b) < '22'::numeric)
10172 -> Foreign Scan on public.fpagg_tab_p1 t1
10173 Output: t1.a, t1.*, t1.b
10174 Remote SQL: SELECT a, b, c FROM public.pagg_tab_p1 ORDER BY a ASC NULLS LAST
10176 Output: t1_1.a, count(((t1_1.*)::pagg_tab))
10178 Filter: (avg(t1_1.b) < '22'::numeric)
10179 -> Foreign Scan on public.fpagg_tab_p2 t1_1
10180 Output: t1_1.a, t1_1.*, t1_1.b
10181 Remote SQL: SELECT a, b, c FROM public.pagg_tab_p2 ORDER BY a ASC NULLS LAST
10183 Output: t1_2.a, count(((t1_2.*)::pagg_tab))
10185 Filter: (avg(t1_2.b) < '22'::numeric)
10186 -> Foreign Scan on public.fpagg_tab_p3 t1_2
10187 Output: t1_2.a, t1_2.*, t1_2.b
10188 Remote SQL: SELECT a, b, c FROM public.pagg_tab_p3 ORDER BY a ASC NULLS LAST
10191 SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1;
10202 -- When GROUP BY clause does not match with PARTITION KEY.
10203 EXPLAIN (COSTS OFF)
10204 SELECT b, avg(a), max(a), count(*) FROM pagg_tab GROUP BY b HAVING sum(a) < 700 ORDER BY 1;
10206 -----------------------------------------------------------
10207 Finalize GroupAggregate
10208 Group Key: pagg_tab.b
10209 Filter: (sum(pagg_tab.a) < 700)
10211 Sort Key: pagg_tab.b
10212 -> Partial GroupAggregate
10213 Group Key: pagg_tab.b
10214 -> Foreign Scan on fpagg_tab_p1 pagg_tab
10215 -> Partial GroupAggregate
10216 Group Key: pagg_tab_1.b
10217 -> Foreign Scan on fpagg_tab_p2 pagg_tab_1
10218 -> Partial GroupAggregate
10219 Group Key: pagg_tab_2.b
10220 -> Foreign Scan on fpagg_tab_p3 pagg_tab_2
10223 -- ===================================================================
10224 -- access rights and superuser
10225 -- ===================================================================
10226 -- Non-superuser cannot create a FDW without a password in the connstr
10227 CREATE ROLE regress_nosuper NOSUPERUSER;
10228 GRANT USAGE ON FOREIGN DATA WRAPPER postgres_fdw TO regress_nosuper;
10229 SET ROLE regress_nosuper;
10236 -- This will be OK, we can create the FDW
10239 EXECUTE $$CREATE SERVER loopback_nopw FOREIGN DATA WRAPPER postgres_fdw
10240 OPTIONS (dbname '$$||current_database()||$$',
10241 port '$$||current_setting('port')||$$'
10245 -- But creation of user mappings for non-superusers should fail
10246 CREATE USER MAPPING FOR public SERVER loopback_nopw;
10247 CREATE USER MAPPING FOR CURRENT_USER SERVER loopback_nopw;
10248 CREATE FOREIGN TABLE pg_temp.ft1_nopw (
10255 c7 char(10) default 'ft1',
10257 ) SERVER loopback_nopw OPTIONS (schema_name 'public', table_name 'ft1');
10258 SELECT 1 FROM ft1_nopw LIMIT 1;
10259 ERROR: password or GSSAPI delegated credentials required
10260 DETAIL: Non-superusers must delegate GSSAPI credentials or provide a password in the user mapping.
10261 -- If we add a password to the connstr it'll fail, because we don't allow passwords
10262 -- in connstrs only in user mappings.
10263 ALTER SERVER loopback_nopw OPTIONS (ADD password 'dummypw');
10264 ERROR: invalid option "password"
10265 HINT: Perhaps you meant the option "passfile".
10266 -- If we add a password for our user mapping instead, we should get a different
10267 -- error because the password wasn't actually *used* when we run with trust auth.
10269 -- This won't work with installcheck, but neither will most of the FDW checks.
10270 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback_nopw OPTIONS (ADD password 'dummypw');
10271 SELECT 1 FROM ft1_nopw LIMIT 1;
10272 ERROR: password or GSSAPI delegated credentials required
10273 DETAIL: Non-superuser cannot connect if the server does not request a password or use GSSAPI with delegated credentials.
10274 HINT: Target server's authentication method must be changed or password_required=false set in the user mapping attributes.
10275 -- Unpriv user cannot make the mapping passwordless
10276 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback_nopw OPTIONS (ADD password_required 'false');
10277 ERROR: password_required=false is superuser-only
10278 HINT: User mappings with the password_required option set to false may only be created or modified by the superuser.
10279 SELECT 1 FROM ft1_nopw LIMIT 1;
10280 ERROR: password or GSSAPI delegated credentials required
10281 DETAIL: Non-superuser cannot connect if the server does not request a password or use GSSAPI with delegated credentials.
10282 HINT: Target server's authentication method must be changed or password_required=false set in the user mapping attributes.
10284 -- But the superuser can
10285 ALTER USER MAPPING FOR regress_nosuper SERVER loopback_nopw OPTIONS (ADD password_required 'false');
10286 SET ROLE regress_nosuper;
10287 -- Should finally work now
10288 SELECT 1 FROM ft1_nopw LIMIT 1;
10294 -- unpriv user also cannot set sslcert / sslkey on the user mapping
10295 -- first set password_required so we see the right error messages
10296 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback_nopw OPTIONS (SET password_required 'true');
10297 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback_nopw OPTIONS (ADD sslcert 'foo.crt');
10298 ERROR: sslcert and sslkey are superuser-only
10299 HINT: User mappings with the sslcert or sslkey options set may only be created or modified by the superuser.
10300 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback_nopw OPTIONS (ADD sslkey 'foo.key');
10301 ERROR: sslcert and sslkey are superuser-only
10302 HINT: User mappings with the sslcert or sslkey options set may only be created or modified by the superuser.
10303 -- We're done with the role named after a specific user and need to check the
10304 -- changes to the public mapping.
10305 DROP USER MAPPING FOR CURRENT_USER SERVER loopback_nopw;
10306 -- This will fail again as it'll resolve the user mapping for public, which
10307 -- lacks password_required=false
10308 SELECT 1 FROM ft1_nopw LIMIT 1;
10309 ERROR: password or GSSAPI delegated credentials required
10310 DETAIL: Non-superusers must delegate GSSAPI credentials or provide a password in the user mapping.
10312 -- The user mapping for public is passwordless and lacks the password_required=false
10313 -- mapping option, but will work because the current user is a superuser.
10314 SELECT 1 FROM ft1_nopw LIMIT 1;
10321 DROP USER MAPPING FOR public SERVER loopback_nopw;
10322 DROP OWNED BY regress_nosuper;
10323 DROP ROLE regress_nosuper;
10325 RESET enable_partitionwise_aggregate;
10326 -- Two-phase transactions are not supported.
10328 SELECT count(*) FROM ft1;
10335 PREPARE TRANSACTION 'fdw_tpc';
10336 ERROR: cannot PREPARE a transaction that has operated on postgres_fdw foreign tables
10338 WARNING: there is no transaction in progress
10339 -- ===================================================================
10340 -- reestablish new connection
10341 -- ===================================================================
10342 -- Change application_name of remote connection to special one
10343 -- so that we can easily terminate the connection later.
10344 ALTER SERVER loopback OPTIONS (application_name 'fdw_retry_check');
10345 -- Make sure we have a remote connection.
10346 SELECT 1 FROM ft1 LIMIT 1;
10352 -- Terminate the remote connection and wait for the termination to complete.
10353 -- (If a cache flush happens, the remote connection might have already been
10354 -- dropped; so code this step in a way that doesn't fail if no connection.)
10356 PERFORM pg_terminate_backend(pid, 180000) FROM pg_stat_activity
10357 WHERE application_name = 'fdw_retry_check';
10359 -- This query should detect the broken connection when starting new remote
10360 -- transaction, reestablish new connection, and then succeed.
10362 SELECT 1 FROM ft1 LIMIT 1;
10368 -- If we detect the broken connection when starting a new remote
10369 -- subtransaction, we should fail instead of establishing a new connection.
10370 -- Terminate the remote connection and wait for the termination to complete.
10372 PERFORM pg_terminate_backend(pid, 180000) FROM pg_stat_activity
10373 WHERE application_name = 'fdw_retry_check';
10376 -- The text of the error might vary across platforms, so only show SQLSTATE.
10377 \set VERBOSITY sqlstate
10378 SELECT 1 FROM ft1 LIMIT 1; -- should fail
10380 \set VERBOSITY default
10382 -- =============================================================================
10383 -- test connection invalidation cases and postgres_fdw_get_connections function
10384 -- =============================================================================
10385 -- Let's ensure to close all the existing cached connections.
10386 SELECT 1 FROM postgres_fdw_disconnect_all();
10392 -- No cached connections, so no records should be output.
10393 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10398 -- This test case is for closing the connection in pgfdw_xact_callback
10400 -- Connection xact depth becomes 1 i.e. the connection is in midst of the xact.
10401 SELECT 1 FROM ft1 LIMIT 1;
10407 SELECT 1 FROM ft7 LIMIT 1;
10413 -- List all the existing cached connections. loopback and loopback3 should be
10415 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10422 -- Connections are not closed at the end of the alter and drop statements.
10423 -- That's because the connections are in midst of this xact,
10424 -- they are just marked as invalid in pgfdw_inval_callback.
10425 ALTER SERVER loopback OPTIONS (ADD use_remote_estimate 'off');
10426 DROP SERVER loopback3 CASCADE;
10427 NOTICE: drop cascades to 2 other objects
10428 DETAIL: drop cascades to user mapping for public on server loopback3
10429 drop cascades to foreign table ft7
10430 -- List all the existing cached connections. loopback and loopback3
10431 -- should be output as invalid connections. Also the server name for
10432 -- loopback3 should be NULL because the server was dropped.
10433 SELECT * FROM postgres_fdw_get_connections() ORDER BY 1;
10434 server_name | valid
10435 -------------+-------
10440 -- The invalid connections get closed in pgfdw_xact_callback during commit.
10442 -- All cached connections were closed while committing above xact, so no
10443 -- records should be output.
10444 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10449 -- =======================================================================
10450 -- test postgres_fdw_disconnect and postgres_fdw_disconnect_all functions
10451 -- =======================================================================
10453 -- Ensure to cache loopback connection.
10454 SELECT 1 FROM ft1 LIMIT 1;
10460 -- Ensure to cache loopback2 connection.
10461 SELECT 1 FROM ft6 LIMIT 1;
10467 -- List all the existing cached connections. loopback and loopback2 should be
10469 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10476 -- Issue a warning and return false as loopback connection is still in use and
10477 -- can not be closed.
10478 SELECT postgres_fdw_disconnect('loopback');
10479 WARNING: cannot close connection for server "loopback" because it is still in use
10480 postgres_fdw_disconnect
10481 -------------------------
10485 -- List all the existing cached connections. loopback and loopback2 should be
10487 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10494 -- Return false as connections are still in use, warnings are issued.
10495 -- But disable warnings temporarily because the order of them is not stable.
10496 SET client_min_messages = 'ERROR';
10497 SELECT postgres_fdw_disconnect_all();
10498 postgres_fdw_disconnect_all
10499 -----------------------------
10503 RESET client_min_messages;
10505 -- Ensure that loopback2 connection is closed.
10506 SELECT 1 FROM postgres_fdw_disconnect('loopback2');
10512 SELECT server_name FROM postgres_fdw_get_connections() WHERE server_name = 'loopback2';
10517 -- Return false as loopback2 connection is closed already.
10518 SELECT postgres_fdw_disconnect('loopback2');
10519 postgres_fdw_disconnect
10520 -------------------------
10524 -- Return an error as there is no foreign server with given name.
10525 SELECT postgres_fdw_disconnect('unknownserver');
10526 ERROR: server "unknownserver" does not exist
10527 -- Let's ensure to close all the existing cached connections.
10528 SELECT 1 FROM postgres_fdw_disconnect_all();
10534 -- No cached connections, so no records should be output.
10535 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10540 -- =============================================================================
10541 -- test case for having multiple cached connections for a foreign server
10542 -- =============================================================================
10543 CREATE ROLE regress_multi_conn_user1 SUPERUSER;
10544 CREATE ROLE regress_multi_conn_user2 SUPERUSER;
10545 CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER loopback;
10546 CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER loopback;
10548 -- Will cache loopback connection with user mapping for regress_multi_conn_user1
10549 SET ROLE regress_multi_conn_user1;
10550 SELECT 1 FROM ft1 LIMIT 1;
10557 -- Will cache loopback connection with user mapping for regress_multi_conn_user2
10558 SET ROLE regress_multi_conn_user2;
10559 SELECT 1 FROM ft1 LIMIT 1;
10566 -- Should output two connections for loopback server
10567 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10575 -- Let's ensure to close all the existing cached connections.
10576 SELECT 1 FROM postgres_fdw_disconnect_all();
10582 -- No cached connections, so no records should be output.
10583 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10589 DROP USER MAPPING FOR regress_multi_conn_user1 SERVER loopback;
10590 DROP USER MAPPING FOR regress_multi_conn_user2 SERVER loopback;
10591 DROP ROLE regress_multi_conn_user1;
10592 DROP ROLE regress_multi_conn_user2;
10593 -- ===================================================================
10594 -- Test foreign server level option keep_connections
10595 -- ===================================================================
10596 -- By default, the connections associated with foreign server are cached i.e.
10597 -- keep_connections option is on. Set it to off.
10598 ALTER SERVER loopback OPTIONS (keep_connections 'off');
10599 -- connection to loopback server is closed at the end of xact
10600 -- as keep_connections was set to off.
10601 SELECT 1 FROM ft1 LIMIT 1;
10607 -- No cached connections, so no records should be output.
10608 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10613 ALTER SERVER loopback OPTIONS (SET keep_connections 'on');
10614 -- ===================================================================
10616 -- ===================================================================
10618 CREATE SERVER batch10 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( batch_size '10' );
10620 FROM pg_foreign_server
10621 WHERE srvname = 'batch10'
10622 AND srvoptions @> array['batch_size=10'];
10628 ALTER SERVER batch10 OPTIONS( SET batch_size '20' );
10630 FROM pg_foreign_server
10631 WHERE srvname = 'batch10'
10632 AND srvoptions @> array['batch_size=10'];
10639 FROM pg_foreign_server
10640 WHERE srvname = 'batch10'
10641 AND srvoptions @> array['batch_size=20'];
10647 CREATE FOREIGN TABLE table30 ( x int ) SERVER batch10 OPTIONS ( batch_size '30' );
10649 FROM pg_foreign_table
10650 WHERE ftrelid = 'table30'::regclass
10651 AND ftoptions @> array['batch_size=30'];
10657 ALTER FOREIGN TABLE table30 OPTIONS ( SET batch_size '40');
10659 FROM pg_foreign_table
10660 WHERE ftrelid = 'table30'::regclass
10661 AND ftoptions @> array['batch_size=30'];
10668 FROM pg_foreign_table
10669 WHERE ftrelid = 'table30'::regclass
10670 AND ftoptions @> array['batch_size=40'];
10677 CREATE TABLE batch_table ( x int );
10678 CREATE FOREIGN TABLE ftable ( x int ) SERVER loopback OPTIONS ( table_name 'batch_table', batch_size '10' );
10679 EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable SELECT * FROM generate_series(1, 10) i;
10681 -------------------------------------------------------------
10682 Insert on public.ftable
10683 Remote SQL: INSERT INTO public.batch_table(x) VALUES ($1)
10685 -> Function Scan on pg_catalog.generate_series i
10687 Function Call: generate_series(1, 10)
10690 INSERT INTO ftable SELECT * FROM generate_series(1, 10) i;
10691 INSERT INTO ftable SELECT * FROM generate_series(11, 31) i;
10692 INSERT INTO ftable VALUES (32);
10693 INSERT INTO ftable VALUES (33), (34);
10694 SELECT COUNT(*) FROM ftable;
10700 TRUNCATE batch_table;
10701 DROP FOREIGN TABLE ftable;
10702 -- Disable batch insert
10703 CREATE FOREIGN TABLE ftable ( x int ) SERVER loopback OPTIONS ( table_name 'batch_table', batch_size '1' );
10704 EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable VALUES (1), (2);
10706 -------------------------------------------------------------
10707 Insert on public.ftable
10708 Remote SQL: INSERT INTO public.batch_table(x) VALUES ($1)
10710 -> Values Scan on "*VALUES*"
10711 Output: "*VALUES*".column1
10714 INSERT INTO ftable VALUES (1), (2);
10715 SELECT COUNT(*) FROM ftable;
10721 -- Disable batch inserting into foreign tables with BEFORE ROW INSERT triggers
10722 -- even if the batch_size option is enabled.
10723 ALTER FOREIGN TABLE ftable OPTIONS ( SET batch_size '10' );
10724 CREATE TRIGGER trig_row_before BEFORE INSERT ON ftable
10725 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
10726 EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable VALUES (3), (4);
10728 -------------------------------------------------------------
10729 Insert on public.ftable
10730 Remote SQL: INSERT INTO public.batch_table(x) VALUES ($1)
10732 -> Values Scan on "*VALUES*"
10733 Output: "*VALUES*".column1
10736 INSERT INTO ftable VALUES (3), (4);
10737 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON ftable
10739 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON ftable
10741 SELECT COUNT(*) FROM ftable;
10748 DROP TRIGGER trig_row_before ON ftable;
10749 DROP FOREIGN TABLE ftable;
10750 DROP TABLE batch_table;
10751 -- Use partitioning
10752 CREATE TABLE batch_table ( x int ) PARTITION BY HASH (x);
10753 CREATE TABLE batch_table_p0 (LIKE batch_table);
10754 CREATE FOREIGN TABLE batch_table_p0f
10755 PARTITION OF batch_table
10756 FOR VALUES WITH (MODULUS 3, REMAINDER 0)
10758 OPTIONS (table_name 'batch_table_p0', batch_size '10');
10759 CREATE TABLE batch_table_p1 (LIKE batch_table);
10760 CREATE FOREIGN TABLE batch_table_p1f
10761 PARTITION OF batch_table
10762 FOR VALUES WITH (MODULUS 3, REMAINDER 1)
10764 OPTIONS (table_name 'batch_table_p1', batch_size '1');
10765 CREATE TABLE batch_table_p2
10766 PARTITION OF batch_table
10767 FOR VALUES WITH (MODULUS 3, REMAINDER 2);
10768 INSERT INTO batch_table SELECT * FROM generate_series(1, 66) i;
10769 SELECT COUNT(*) FROM batch_table;
10776 DROP TABLE batch_table;
10777 DROP TABLE batch_table_p0;
10778 DROP TABLE batch_table_p1;
10779 -- Check that batched mode also works for some inserts made during
10780 -- cross-partition updates
10781 CREATE TABLE batch_cp_upd_test (a int) PARTITION BY LIST (a);
10782 CREATE TABLE batch_cp_upd_test1 (LIKE batch_cp_upd_test);
10783 CREATE FOREIGN TABLE batch_cp_upd_test1_f
10784 PARTITION OF batch_cp_upd_test
10787 OPTIONS (table_name 'batch_cp_upd_test1', batch_size '10');
10788 CREATE TABLE batch_cp_upd_test2 PARTITION OF batch_cp_upd_test
10790 CREATE TABLE batch_cp_upd_test3 (LIKE batch_cp_upd_test);
10791 CREATE FOREIGN TABLE batch_cp_upd_test3_f
10792 PARTITION OF batch_cp_upd_test
10795 OPTIONS (table_name 'batch_cp_upd_test3', batch_size '1');
10796 -- Create statement triggers on remote tables that "log" any INSERTs
10797 -- performed on them.
10798 CREATE TABLE cmdlog (cmd text);
10799 CREATE FUNCTION log_stmt() RETURNS TRIGGER LANGUAGE plpgsql AS $$
10800 BEGIN INSERT INTO public.cmdlog VALUES (TG_OP || ' on ' || TG_RELNAME); RETURN NULL; END;
10802 CREATE TRIGGER stmt_trig AFTER INSERT ON batch_cp_upd_test1
10803 FOR EACH STATEMENT EXECUTE FUNCTION log_stmt();
10804 CREATE TRIGGER stmt_trig AFTER INSERT ON batch_cp_upd_test3
10805 FOR EACH STATEMENT EXECUTE FUNCTION log_stmt();
10806 -- This update moves rows from the local partition 'batch_cp_upd_test2' to the
10807 -- foreign partition 'batch_cp_upd_test1', one that has insert batching
10808 -- enabled, so a single INSERT for both rows.
10809 INSERT INTO batch_cp_upd_test VALUES (2), (2);
10810 UPDATE batch_cp_upd_test t SET a = 1 FROM (VALUES (1), (2)) s(a) WHERE t.a = s.a AND s.a = 2;
10811 -- This one moves rows from the local partition 'batch_cp_upd_test2' to the
10812 -- foreign partition 'batch_cp_upd_test2', one that has insert batching
10813 -- disabled, so separate INSERTs for the two rows.
10814 INSERT INTO batch_cp_upd_test VALUES (2), (2);
10815 UPDATE batch_cp_upd_test t SET a = 3 FROM (VALUES (1), (2)) s(a) WHERE t.a = s.a AND s.a = 2;
10816 SELECT tableoid::regclass, * FROM batch_cp_upd_test ORDER BY 1;
10818 ----------------------+---
10819 batch_cp_upd_test1_f | 1
10820 batch_cp_upd_test1_f | 1
10821 batch_cp_upd_test3_f | 3
10822 batch_cp_upd_test3_f | 3
10825 -- Should see 1 INSERT on batch_cp_upd_test1 and 2 on batch_cp_upd_test3 as
10826 -- described above.
10827 SELECT * FROM cmdlog ORDER BY 1;
10829 ------------------------------
10830 INSERT on batch_cp_upd_test1
10831 INSERT on batch_cp_upd_test3
10832 INSERT on batch_cp_upd_test3
10836 DROP TABLE batch_cp_upd_test;
10837 DROP TABLE batch_cp_upd_test1;
10838 DROP TABLE batch_cp_upd_test3;
10840 DROP FUNCTION log_stmt();
10841 -- Use partitioning
10842 ALTER SERVER loopback OPTIONS (ADD batch_size '10');
10843 CREATE TABLE batch_table ( x int, field1 text, field2 text) PARTITION BY HASH (x);
10844 CREATE TABLE batch_table_p0 (LIKE batch_table);
10845 ALTER TABLE batch_table_p0 ADD CONSTRAINT p0_pkey PRIMARY KEY (x);
10846 CREATE FOREIGN TABLE batch_table_p0f
10847 PARTITION OF batch_table
10848 FOR VALUES WITH (MODULUS 2, REMAINDER 0)
10850 OPTIONS (table_name 'batch_table_p0');
10851 CREATE TABLE batch_table_p1 (LIKE batch_table);
10852 ALTER TABLE batch_table_p1 ADD CONSTRAINT p1_pkey PRIMARY KEY (x);
10853 CREATE FOREIGN TABLE batch_table_p1f
10854 PARTITION OF batch_table
10855 FOR VALUES WITH (MODULUS 2, REMAINDER 1)
10857 OPTIONS (table_name 'batch_table_p1');
10858 INSERT INTO batch_table SELECT i, 'test'||i, 'test'|| i FROM generate_series(1, 50) i;
10859 SELECT COUNT(*) FROM batch_table;
10865 SELECT * FROM batch_table ORDER BY x;
10866 x | field1 | field2
10867 ----+--------+--------
10877 10 | test10 | test10
10878 11 | test11 | test11
10879 12 | test12 | test12
10880 13 | test13 | test13
10881 14 | test14 | test14
10882 15 | test15 | test15
10883 16 | test16 | test16
10884 17 | test17 | test17
10885 18 | test18 | test18
10886 19 | test19 | test19
10887 20 | test20 | test20
10888 21 | test21 | test21
10889 22 | test22 | test22
10890 23 | test23 | test23
10891 24 | test24 | test24
10892 25 | test25 | test25
10893 26 | test26 | test26
10894 27 | test27 | test27
10895 28 | test28 | test28
10896 29 | test29 | test29
10897 30 | test30 | test30
10898 31 | test31 | test31
10899 32 | test32 | test32
10900 33 | test33 | test33
10901 34 | test34 | test34
10902 35 | test35 | test35
10903 36 | test36 | test36
10904 37 | test37 | test37
10905 38 | test38 | test38
10906 39 | test39 | test39
10907 40 | test40 | test40
10908 41 | test41 | test41
10909 42 | test42 | test42
10910 43 | test43 | test43
10911 44 | test44 | test44
10912 45 | test45 | test45
10913 46 | test46 | test46
10914 47 | test47 | test47
10915 48 | test48 | test48
10916 49 | test49 | test49
10917 50 | test50 | test50
10921 DROP TABLE batch_table;
10922 DROP TABLE batch_table_p0;
10923 DROP TABLE batch_table_p1;
10924 ALTER SERVER loopback OPTIONS (DROP batch_size);
10925 -- Test that pending inserts are handled properly when needed
10926 CREATE TABLE batch_table (a text, b int);
10927 CREATE FOREIGN TABLE ftable (a text, b int)
10929 OPTIONS (table_name 'batch_table', batch_size '2');
10930 CREATE TABLE ltable (a text, b int);
10931 CREATE FUNCTION ftable_rowcount_trigf() RETURNS trigger LANGUAGE plpgsql AS
10934 raise notice '%: there are % rows in ftable',
10935 TG_NAME, (SELECT count(*) FROM ftable);
10936 if TG_OP = 'DELETE' then
10943 CREATE TRIGGER ftable_rowcount_trigger
10944 BEFORE INSERT OR UPDATE OR DELETE ON ltable
10945 FOR EACH ROW EXECUTE PROCEDURE ftable_rowcount_trigf();
10947 INSERT INTO ltable VALUES ('AAA', 42), ('BBB', 42) RETURNING *
10949 INSERT INTO ftable SELECT * FROM t;
10950 NOTICE: ftable_rowcount_trigger: there are 0 rows in ftable
10951 NOTICE: ftable_rowcount_trigger: there are 1 rows in ftable
10952 SELECT * FROM ltable;
10959 SELECT * FROM ftable;
10966 DELETE FROM ftable;
10968 UPDATE ltable SET b = b + 100 RETURNING *
10970 INSERT INTO ftable SELECT * FROM t;
10971 NOTICE: ftable_rowcount_trigger: there are 0 rows in ftable
10972 NOTICE: ftable_rowcount_trigger: there are 1 rows in ftable
10973 SELECT * FROM ltable;
10980 SELECT * FROM ftable;
10987 DELETE FROM ftable;
10989 DELETE FROM ltable RETURNING *
10991 INSERT INTO ftable SELECT * FROM t;
10992 NOTICE: ftable_rowcount_trigger: there are 0 rows in ftable
10993 NOTICE: ftable_rowcount_trigger: there are 1 rows in ftable
10994 SELECT * FROM ltable;
10999 SELECT * FROM ftable;
11006 DELETE FROM ftable;
11008 DROP FOREIGN TABLE ftable;
11009 DROP TABLE batch_table;
11010 DROP TRIGGER ftable_rowcount_trigger ON ltable;
11012 CREATE TABLE parent (a text, b int) PARTITION BY LIST (a);
11013 CREATE TABLE batch_table (a text, b int);
11014 CREATE FOREIGN TABLE ftable
11015 PARTITION OF parent
11016 FOR VALUES IN ('AAA')
11018 OPTIONS (table_name 'batch_table', batch_size '2');
11019 CREATE TABLE ltable
11020 PARTITION OF parent
11021 FOR VALUES IN ('BBB');
11022 CREATE TRIGGER ftable_rowcount_trigger
11023 BEFORE INSERT ON ltable
11024 FOR EACH ROW EXECUTE PROCEDURE ftable_rowcount_trigf();
11025 INSERT INTO parent VALUES ('AAA', 42), ('BBB', 42), ('AAA', 42), ('BBB', 42);
11026 NOTICE: ftable_rowcount_trigger: there are 1 rows in ftable
11027 NOTICE: ftable_rowcount_trigger: there are 2 rows in ftable
11028 SELECT tableoid::regclass, * FROM parent;
11030 ----------+-----+----
11038 DROP FOREIGN TABLE ftable;
11039 DROP TABLE batch_table;
11040 DROP TRIGGER ftable_rowcount_trigger ON ltable;
11043 DROP FUNCTION ftable_rowcount_trigf;
11044 -- ===================================================================
11045 -- test asynchronous execution
11046 -- ===================================================================
11047 ALTER SERVER loopback OPTIONS (DROP extensions);
11048 ALTER SERVER loopback OPTIONS (ADD async_capable 'true');
11049 ALTER SERVER loopback2 OPTIONS (ADD async_capable 'true');
11050 CREATE TABLE async_pt (a int, b int, c text) PARTITION BY RANGE (a);
11051 CREATE TABLE base_tbl1 (a int, b int, c text);
11052 CREATE TABLE base_tbl2 (a int, b int, c text);
11053 CREATE FOREIGN TABLE async_p1 PARTITION OF async_pt FOR VALUES FROM (1000) TO (2000)
11054 SERVER loopback OPTIONS (table_name 'base_tbl1');
11055 CREATE FOREIGN TABLE async_p2 PARTITION OF async_pt FOR VALUES FROM (2000) TO (3000)
11056 SERVER loopback2 OPTIONS (table_name 'base_tbl2');
11057 INSERT INTO async_p1 SELECT 1000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i;
11058 INSERT INTO async_p2 SELECT 2000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i;
11061 CREATE TABLE result_tbl (a int, b int, c text);
11062 EXPLAIN (VERBOSE, COSTS OFF)
11063 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b % 100 = 0;
11065 ----------------------------------------------------------------------------------------
11066 Insert on public.result_tbl
11068 -> Async Foreign Scan on public.async_p1 async_pt_1
11069 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11070 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE (((b % 100) = 0))
11071 -> Async Foreign Scan on public.async_p2 async_pt_2
11072 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11073 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE (((b % 100) = 0))
11076 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b % 100 = 0;
11077 SELECT * FROM result_tbl ORDER BY a;
11079 ------+-----+------
11102 DELETE FROM result_tbl;
11103 EXPLAIN (VERBOSE, COSTS OFF)
11104 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11106 ----------------------------------------------------------------
11107 Insert on public.result_tbl
11109 -> Async Foreign Scan on public.async_p1 async_pt_1
11110 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11111 Filter: (async_pt_1.b === 505)
11112 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11113 -> Async Foreign Scan on public.async_p2 async_pt_2
11114 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11115 Filter: (async_pt_2.b === 505)
11116 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11119 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11120 SELECT * FROM result_tbl ORDER BY a;
11122 ------+-----+------
11127 DELETE FROM result_tbl;
11128 EXPLAIN (VERBOSE, COSTS OFF)
11129 INSERT INTO result_tbl SELECT a, b, 'AAA' || c FROM async_pt WHERE b === 505;
11131 ---------------------------------------------------------------------------------
11132 Insert on public.result_tbl
11134 -> Async Foreign Scan on public.async_p1 async_pt_1
11135 Output: async_pt_1.a, async_pt_1.b, ('AAA'::text || async_pt_1.c)
11136 Filter: (async_pt_1.b === 505)
11137 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11138 -> Async Foreign Scan on public.async_p2 async_pt_2
11139 Output: async_pt_2.a, async_pt_2.b, ('AAA'::text || async_pt_2.c)
11140 Filter: (async_pt_2.b === 505)
11141 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11144 INSERT INTO result_tbl SELECT a, b, 'AAA' || c FROM async_pt WHERE b === 505;
11145 SELECT * FROM result_tbl ORDER BY a;
11147 ------+-----+---------
11148 1505 | 505 | AAA0505
11149 2505 | 505 | AAA0505
11152 DELETE FROM result_tbl;
11153 -- Test error handling, if accessing one of the foreign partitions errors out
11154 CREATE FOREIGN TABLE async_p_broken PARTITION OF async_pt FOR VALUES FROM (10000) TO (10001)
11155 SERVER loopback OPTIONS (table_name 'non_existent_table');
11156 SELECT * FROM async_pt;
11157 ERROR: relation "public.non_existent_table" does not exist
11158 CONTEXT: remote SQL command: SELECT a, b, c FROM public.non_existent_table
11159 DROP FOREIGN TABLE async_p_broken;
11160 -- Check case where multiple partitions use the same connection
11161 CREATE TABLE base_tbl3 (a int, b int, c text);
11162 CREATE FOREIGN TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000)
11163 SERVER loopback2 OPTIONS (table_name 'base_tbl3');
11164 INSERT INTO async_p3 SELECT 3000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i;
11166 EXPLAIN (VERBOSE, COSTS OFF)
11167 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11169 ----------------------------------------------------------------
11170 Insert on public.result_tbl
11172 -> Async Foreign Scan on public.async_p1 async_pt_1
11173 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11174 Filter: (async_pt_1.b === 505)
11175 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11176 -> Async Foreign Scan on public.async_p2 async_pt_2
11177 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11178 Filter: (async_pt_2.b === 505)
11179 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11180 -> Async Foreign Scan on public.async_p3 async_pt_3
11181 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11182 Filter: (async_pt_3.b === 505)
11183 Remote SQL: SELECT a, b, c FROM public.base_tbl3
11186 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11187 SELECT * FROM result_tbl ORDER BY a;
11189 ------+-----+------
11195 DELETE FROM result_tbl;
11196 DROP FOREIGN TABLE async_p3;
11197 DROP TABLE base_tbl3;
11198 -- Check case where the partitioned table has local/remote partitions
11199 CREATE TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000);
11200 INSERT INTO async_p3 SELECT 3000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i;
11202 EXPLAIN (VERBOSE, COSTS OFF)
11203 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11205 ----------------------------------------------------------------
11206 Insert on public.result_tbl
11208 -> Async Foreign Scan on public.async_p1 async_pt_1
11209 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11210 Filter: (async_pt_1.b === 505)
11211 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11212 -> Async Foreign Scan on public.async_p2 async_pt_2
11213 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11214 Filter: (async_pt_2.b === 505)
11215 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11216 -> Seq Scan on public.async_p3 async_pt_3
11217 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11218 Filter: (async_pt_3.b === 505)
11221 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11222 SELECT * FROM result_tbl ORDER BY a;
11224 ------+-----+------
11230 DELETE FROM result_tbl;
11231 -- partitionwise joins
11232 SET enable_partitionwise_join TO true;
11233 CREATE TABLE join_tbl (a1 int, b1 int, c1 text, a2 int, b2 int, c2 text);
11234 EXPLAIN (VERBOSE, COSTS OFF)
11235 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;
11237 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
11238 Insert on public.join_tbl
11240 -> Async Foreign Scan
11241 Output: t1_1.a, t1_1.b, t1_1.c, t2_1.a, t2_1.b, t2_1.c
11242 Relations: (public.async_p1 t1_1) INNER JOIN (public.async_p1 t2_1)
11243 Remote SQL: SELECT r5.a, r5.b, r5.c, r8.a, r8.b, r8.c FROM (public.base_tbl1 r5 INNER JOIN public.base_tbl1 r8 ON (((r5.a = r8.a)) AND ((r5.b = r8.b)) AND (((r5.b % 100) = 0))))
11244 -> Async Foreign Scan
11245 Output: t1_2.a, t1_2.b, t1_2.c, t2_2.a, t2_2.b, t2_2.c
11246 Relations: (public.async_p2 t1_2) INNER JOIN (public.async_p2 t2_2)
11247 Remote SQL: SELECT r6.a, r6.b, r6.c, r9.a, r9.b, r9.c FROM (public.base_tbl2 r6 INNER JOIN public.base_tbl2 r9 ON (((r6.a = r9.a)) AND ((r6.b = r9.b)) AND (((r6.b % 100) = 0))))
11249 Output: t1_3.a, t1_3.b, t1_3.c, t2_3.a, t2_3.b, t2_3.c
11250 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.b = t1_3.b))
11251 -> Seq Scan on public.async_p3 t2_3
11252 Output: t2_3.a, t2_3.b, t2_3.c
11254 Output: t1_3.a, t1_3.b, t1_3.c
11255 -> Seq Scan on public.async_p3 t1_3
11256 Output: t1_3.a, t1_3.b, t1_3.c
11257 Filter: ((t1_3.b % 100) = 0)
11260 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;
11261 SELECT * FROM join_tbl ORDER BY a1;
11262 a1 | b1 | c1 | a2 | b2 | c2
11263 ------+-----+------+------+-----+------
11264 1000 | 0 | 0000 | 1000 | 0 | 0000
11265 1100 | 100 | 0100 | 1100 | 100 | 0100
11266 1200 | 200 | 0200 | 1200 | 200 | 0200
11267 1300 | 300 | 0300 | 1300 | 300 | 0300
11268 1400 | 400 | 0400 | 1400 | 400 | 0400
11269 1500 | 500 | 0500 | 1500 | 500 | 0500
11270 1600 | 600 | 0600 | 1600 | 600 | 0600
11271 1700 | 700 | 0700 | 1700 | 700 | 0700
11272 1800 | 800 | 0800 | 1800 | 800 | 0800
11273 1900 | 900 | 0900 | 1900 | 900 | 0900
11274 2000 | 0 | 0000 | 2000 | 0 | 0000
11275 2100 | 100 | 0100 | 2100 | 100 | 0100
11276 2200 | 200 | 0200 | 2200 | 200 | 0200
11277 2300 | 300 | 0300 | 2300 | 300 | 0300
11278 2400 | 400 | 0400 | 2400 | 400 | 0400
11279 2500 | 500 | 0500 | 2500 | 500 | 0500
11280 2600 | 600 | 0600 | 2600 | 600 | 0600
11281 2700 | 700 | 0700 | 2700 | 700 | 0700
11282 2800 | 800 | 0800 | 2800 | 800 | 0800
11283 2900 | 900 | 0900 | 2900 | 900 | 0900
11284 3000 | 0 | 0000 | 3000 | 0 | 0000
11285 3100 | 100 | 0100 | 3100 | 100 | 0100
11286 3200 | 200 | 0200 | 3200 | 200 | 0200
11287 3300 | 300 | 0300 | 3300 | 300 | 0300
11288 3400 | 400 | 0400 | 3400 | 400 | 0400
11289 3500 | 500 | 0500 | 3500 | 500 | 0500
11290 3600 | 600 | 0600 | 3600 | 600 | 0600
11291 3700 | 700 | 0700 | 3700 | 700 | 0700
11292 3800 | 800 | 0800 | 3800 | 800 | 0800
11293 3900 | 900 | 0900 | 3900 | 900 | 0900
11296 DELETE FROM join_tbl;
11297 EXPLAIN (VERBOSE, COSTS OFF)
11298 INSERT INTO join_tbl SELECT t1.a, t1.b, 'AAA' || t1.c, t2.a, t2.b, 'AAA' || t2.c FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0;
11300 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
11301 Insert on public.join_tbl
11303 -> Async Foreign Scan
11304 Output: t1_1.a, t1_1.b, ('AAA'::text || t1_1.c), t2_1.a, t2_1.b, ('AAA'::text || t2_1.c)
11305 Relations: (public.async_p1 t1_1) INNER JOIN (public.async_p1 t2_1)
11306 Remote SQL: SELECT r5.a, r5.b, r5.c, r8.a, r8.b, r8.c FROM (public.base_tbl1 r5 INNER JOIN public.base_tbl1 r8 ON (((r5.a = r8.a)) AND ((r5.b = r8.b)) AND (((r5.b % 100) = 0))))
11307 -> Async Foreign Scan
11308 Output: t1_2.a, t1_2.b, ('AAA'::text || t1_2.c), t2_2.a, t2_2.b, ('AAA'::text || t2_2.c)
11309 Relations: (public.async_p2 t1_2) INNER JOIN (public.async_p2 t2_2)
11310 Remote SQL: SELECT r6.a, r6.b, r6.c, r9.a, r9.b, r9.c FROM (public.base_tbl2 r6 INNER JOIN public.base_tbl2 r9 ON (((r6.a = r9.a)) AND ((r6.b = r9.b)) AND (((r6.b % 100) = 0))))
11312 Output: t1_3.a, t1_3.b, ('AAA'::text || t1_3.c), t2_3.a, t2_3.b, ('AAA'::text || t2_3.c)
11313 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.b = t1_3.b))
11314 -> Seq Scan on public.async_p3 t2_3
11315 Output: t2_3.a, t2_3.b, t2_3.c
11317 Output: t1_3.a, t1_3.b, t1_3.c
11318 -> Seq Scan on public.async_p3 t1_3
11319 Output: t1_3.a, t1_3.b, t1_3.c
11320 Filter: ((t1_3.b % 100) = 0)
11323 INSERT INTO join_tbl SELECT t1.a, t1.b, 'AAA' || t1.c, t2.a, t2.b, 'AAA' || t2.c FROM async_pt t1, async_pt t2 WHERE t1.a = t2.a AND t1.b = t2.b AND t1.b % 100 = 0;
11324 SELECT * FROM join_tbl ORDER BY a1;
11325 a1 | b1 | c1 | a2 | b2 | c2
11326 ------+-----+---------+------+-----+---------
11327 1000 | 0 | AAA0000 | 1000 | 0 | AAA0000
11328 1100 | 100 | AAA0100 | 1100 | 100 | AAA0100
11329 1200 | 200 | AAA0200 | 1200 | 200 | AAA0200
11330 1300 | 300 | AAA0300 | 1300 | 300 | AAA0300
11331 1400 | 400 | AAA0400 | 1400 | 400 | AAA0400
11332 1500 | 500 | AAA0500 | 1500 | 500 | AAA0500
11333 1600 | 600 | AAA0600 | 1600 | 600 | AAA0600
11334 1700 | 700 | AAA0700 | 1700 | 700 | AAA0700
11335 1800 | 800 | AAA0800 | 1800 | 800 | AAA0800
11336 1900 | 900 | AAA0900 | 1900 | 900 | AAA0900
11337 2000 | 0 | AAA0000 | 2000 | 0 | AAA0000
11338 2100 | 100 | AAA0100 | 2100 | 100 | AAA0100
11339 2200 | 200 | AAA0200 | 2200 | 200 | AAA0200
11340 2300 | 300 | AAA0300 | 2300 | 300 | AAA0300
11341 2400 | 400 | AAA0400 | 2400 | 400 | AAA0400
11342 2500 | 500 | AAA0500 | 2500 | 500 | AAA0500
11343 2600 | 600 | AAA0600 | 2600 | 600 | AAA0600
11344 2700 | 700 | AAA0700 | 2700 | 700 | AAA0700
11345 2800 | 800 | AAA0800 | 2800 | 800 | AAA0800
11346 2900 | 900 | AAA0900 | 2900 | 900 | AAA0900
11347 3000 | 0 | AAA0000 | 3000 | 0 | AAA0000
11348 3100 | 100 | AAA0100 | 3100 | 100 | AAA0100
11349 3200 | 200 | AAA0200 | 3200 | 200 | AAA0200
11350 3300 | 300 | AAA0300 | 3300 | 300 | AAA0300
11351 3400 | 400 | AAA0400 | 3400 | 400 | AAA0400
11352 3500 | 500 | AAA0500 | 3500 | 500 | AAA0500
11353 3600 | 600 | AAA0600 | 3600 | 600 | AAA0600
11354 3700 | 700 | AAA0700 | 3700 | 700 | AAA0700
11355 3800 | 800 | AAA0800 | 3800 | 800 | AAA0800
11356 3900 | 900 | AAA0900 | 3900 | 900 | AAA0900
11359 DELETE FROM join_tbl;
11360 RESET enable_partitionwise_join;
11361 -- Test rescan of an async Append node with do_exec_prune=false
11362 SET enable_hashjoin TO false;
11363 EXPLAIN (VERBOSE, COSTS OFF)
11364 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;
11366 ----------------------------------------------------------------------------------------
11367 Insert on public.join_tbl
11369 Output: t1.a, t1.b, t1.c, t2.a, t2.b, t2.c
11370 Join Filter: ((t1.a = t2.a) AND (t1.b = t2.b))
11371 -> Foreign Scan on public.async_p1 t1
11372 Output: t1.a, t1.b, t1.c
11373 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE (((b % 100) = 0))
11375 -> Async Foreign Scan on public.async_p1 t2_1
11376 Output: t2_1.a, t2_1.b, t2_1.c
11377 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11378 -> Async Foreign Scan on public.async_p2 t2_2
11379 Output: t2_2.a, t2_2.b, t2_2.c
11380 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11381 -> Seq Scan on public.async_p3 t2_3
11382 Output: t2_3.a, t2_3.b, t2_3.c
11385 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;
11386 SELECT * FROM join_tbl ORDER BY a1;
11387 a1 | b1 | c1 | a2 | b2 | c2
11388 ------+-----+------+------+-----+------
11389 1000 | 0 | 0000 | 1000 | 0 | 0000
11390 1100 | 100 | 0100 | 1100 | 100 | 0100
11391 1200 | 200 | 0200 | 1200 | 200 | 0200
11392 1300 | 300 | 0300 | 1300 | 300 | 0300
11393 1400 | 400 | 0400 | 1400 | 400 | 0400
11394 1500 | 500 | 0500 | 1500 | 500 | 0500
11395 1600 | 600 | 0600 | 1600 | 600 | 0600
11396 1700 | 700 | 0700 | 1700 | 700 | 0700
11397 1800 | 800 | 0800 | 1800 | 800 | 0800
11398 1900 | 900 | 0900 | 1900 | 900 | 0900
11401 DELETE FROM join_tbl;
11402 RESET enable_hashjoin;
11403 -- Test interaction of async execution with plan-time partition pruning
11404 EXPLAIN (VERBOSE, COSTS OFF)
11405 SELECT * FROM async_pt WHERE a < 3000;
11407 -----------------------------------------------------------------------------
11409 -> Async Foreign Scan on public.async_p1 async_pt_1
11410 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11411 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < 3000))
11412 -> Async Foreign Scan on public.async_p2 async_pt_2
11413 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11414 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a < 3000))
11417 EXPLAIN (VERBOSE, COSTS OFF)
11418 SELECT * FROM async_pt WHERE a < 2000;
11420 -----------------------------------------------------------------------
11421 Foreign Scan on public.async_p1 async_pt
11422 Output: async_pt.a, async_pt.b, async_pt.c
11423 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < 2000))
11426 -- Test interaction of async execution with run-time partition pruning
11427 SET plan_cache_mode TO force_generic_plan;
11428 PREPARE async_pt_query (int, int) AS
11429 INSERT INTO result_tbl SELECT * FROM async_pt WHERE a < $1 AND b === $2;
11430 EXPLAIN (VERBOSE, COSTS OFF)
11431 EXECUTE async_pt_query (3000, 505);
11433 ------------------------------------------------------------------------------------------
11434 Insert on public.result_tbl
11436 Subplans Removed: 1
11437 -> Async Foreign Scan on public.async_p1 async_pt_1
11438 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11439 Filter: (async_pt_1.b === $2)
11440 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < $1::integer))
11441 -> Async Foreign Scan on public.async_p2 async_pt_2
11442 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11443 Filter: (async_pt_2.b === $2)
11444 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a < $1::integer))
11447 EXECUTE async_pt_query (3000, 505);
11448 SELECT * FROM result_tbl ORDER BY a;
11450 ------+-----+------
11455 DELETE FROM result_tbl;
11456 EXPLAIN (VERBOSE, COSTS OFF)
11457 EXECUTE async_pt_query (2000, 505);
11459 ------------------------------------------------------------------------------------------
11460 Insert on public.result_tbl
11462 Subplans Removed: 2
11463 -> Async Foreign Scan on public.async_p1 async_pt_1
11464 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11465 Filter: (async_pt_1.b === $2)
11466 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < $1::integer))
11469 EXECUTE async_pt_query (2000, 505);
11470 SELECT * FROM result_tbl ORDER BY a;
11472 ------+-----+------
11476 DELETE FROM result_tbl;
11477 RESET plan_cache_mode;
11478 CREATE TABLE local_tbl(a int, b int, c text);
11479 INSERT INTO local_tbl VALUES (1505, 505, 'foo'), (2505, 505, 'bar');
11481 CREATE INDEX base_tbl1_idx ON base_tbl1 (a);
11482 CREATE INDEX base_tbl2_idx ON base_tbl2 (a);
11483 CREATE INDEX async_p3_idx ON async_p3 (a);
11487 ALTER FOREIGN TABLE async_p1 OPTIONS (use_remote_estimate 'true');
11488 ALTER FOREIGN TABLE async_p2 OPTIONS (use_remote_estimate 'true');
11489 EXPLAIN (VERBOSE, COSTS OFF)
11490 SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar';
11492 ------------------------------------------------------------------------------------------
11494 Output: local_tbl.a, local_tbl.b, local_tbl.c, async_pt.a, async_pt.b, async_pt.c
11495 -> Seq Scan on public.local_tbl
11496 Output: local_tbl.a, local_tbl.b, local_tbl.c
11497 Filter: (local_tbl.c = 'bar'::text)
11499 -> Async Foreign Scan on public.async_p1 async_pt_1
11500 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11501 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a = $1::integer))
11502 -> Async Foreign Scan on public.async_p2 async_pt_2
11503 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11504 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a = $1::integer))
11505 -> Seq Scan on public.async_p3 async_pt_3
11506 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11507 Filter: (async_pt_3.a = local_tbl.a)
11510 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
11511 SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar';
11513 -------------------------------------------------------------------------------
11514 Nested Loop (actual rows=1 loops=1)
11515 -> Seq Scan on local_tbl (actual rows=1 loops=1)
11516 Filter: (c = 'bar'::text)
11517 Rows Removed by Filter: 1
11518 -> Append (actual rows=1 loops=1)
11519 -> Async Foreign Scan on async_p1 async_pt_1 (never executed)
11520 -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=1 loops=1)
11521 -> Seq Scan on async_p3 async_pt_3 (never executed)
11522 Filter: (a = local_tbl.a)
11525 SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar';
11526 a | b | c | a | b | c
11527 ------+-----+-----+------+-----+------
11528 2505 | 505 | bar | 2505 | 505 | 0505
11531 ALTER FOREIGN TABLE async_p1 OPTIONS (DROP use_remote_estimate);
11532 ALTER FOREIGN TABLE async_p2 OPTIONS (DROP use_remote_estimate);
11533 DROP TABLE local_tbl;
11534 DROP INDEX base_tbl1_idx;
11535 DROP INDEX base_tbl2_idx;
11536 DROP INDEX async_p3_idx;
11538 SET enable_sort TO off;
11539 SET enable_incremental_sort TO off;
11540 -- Adjust fdw_startup_cost so that we get an unordered path in the Append.
11541 ALTER SERVER loopback2 OPTIONS (ADD fdw_startup_cost '0.00');
11542 EXPLAIN (VERBOSE, COSTS OFF)
11543 INSERT INTO result_tbl
11544 (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10)
11546 (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10);
11548 -----------------------------------------------------------------------------------------------------------------
11549 Insert on public.result_tbl
11551 Output: async_p1.a, async_p1.b, (('AAA'::text || async_p1.c))
11552 Group Key: async_p1.a, async_p1.b, (('AAA'::text || async_p1.c))
11554 -> Async Foreign Scan on public.async_p1
11555 Output: async_p1.a, async_p1.b, ('AAA'::text || async_p1.c)
11556 Remote SQL: SELECT a, b, c FROM public.base_tbl1 ORDER BY a ASC NULLS LAST LIMIT 10::bigint
11557 -> Async Foreign Scan on public.async_p2
11558 Output: async_p2.a, async_p2.b, ('AAA'::text || async_p2.c)
11559 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((b < 10))
11562 INSERT INTO result_tbl
11563 (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10)
11565 (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10);
11566 SELECT * FROM result_tbl ORDER BY a;
11568 ------+----+---------
11571 1010 | 10 | AAA0010
11572 1015 | 15 | AAA0015
11573 1020 | 20 | AAA0020
11574 1025 | 25 | AAA0025
11575 1030 | 30 | AAA0030
11576 1035 | 35 | AAA0035
11577 1040 | 40 | AAA0040
11578 1045 | 45 | AAA0045
11583 DELETE FROM result_tbl;
11584 EXPLAIN (VERBOSE, COSTS OFF)
11585 INSERT INTO result_tbl
11586 (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10)
11588 (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10);
11590 -----------------------------------------------------------------------------------------------------------
11591 Insert on public.result_tbl
11593 -> Async Foreign Scan on public.async_p1
11594 Output: async_p1.a, async_p1.b, ('AAA'::text || async_p1.c)
11595 Remote SQL: SELECT a, b, c FROM public.base_tbl1 ORDER BY a ASC NULLS LAST LIMIT 10::bigint
11596 -> Async Foreign Scan on public.async_p2
11597 Output: async_p2.a, async_p2.b, ('AAA'::text || async_p2.c)
11598 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((b < 10))
11601 INSERT INTO result_tbl
11602 (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10)
11604 (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10);
11605 SELECT * FROM result_tbl ORDER BY a;
11607 ------+----+---------
11610 1010 | 10 | AAA0010
11611 1015 | 15 | AAA0015
11612 1020 | 20 | AAA0020
11613 1025 | 25 | AAA0025
11614 1030 | 30 | AAA0030
11615 1035 | 35 | AAA0035
11616 1040 | 40 | AAA0040
11617 1045 | 45 | AAA0045
11622 DELETE FROM result_tbl;
11623 RESET enable_incremental_sort;
11625 ALTER SERVER loopback2 OPTIONS (DROP fdw_startup_cost);
11626 -- Disable async execution if we use gating Result nodes for pseudoconstant
11628 EXPLAIN (VERBOSE, COSTS OFF)
11629 SELECT * FROM async_pt WHERE CURRENT_USER = SESSION_USER;
11631 ----------------------------------------------------------------
11634 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11635 One-Time Filter: (CURRENT_USER = SESSION_USER)
11636 -> Foreign Scan on public.async_p1 async_pt_1
11637 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11638 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11640 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11641 One-Time Filter: (CURRENT_USER = SESSION_USER)
11642 -> Foreign Scan on public.async_p2 async_pt_2
11643 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11644 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11646 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11647 One-Time Filter: (CURRENT_USER = SESSION_USER)
11648 -> Seq Scan on public.async_p3 async_pt_3
11649 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11652 EXPLAIN (VERBOSE, COSTS OFF)
11653 (SELECT * FROM async_p1 WHERE CURRENT_USER = SESSION_USER)
11655 (SELECT * FROM async_p2 WHERE CURRENT_USER = SESSION_USER);
11657 ----------------------------------------------------------------
11660 Output: async_p1.a, async_p1.b, async_p1.c
11661 One-Time Filter: (CURRENT_USER = SESSION_USER)
11662 -> Foreign Scan on public.async_p1
11663 Output: async_p1.a, async_p1.b, async_p1.c
11664 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11666 Output: async_p2.a, async_p2.b, async_p2.c
11667 One-Time Filter: (CURRENT_USER = SESSION_USER)
11668 -> Foreign Scan on public.async_p2
11669 Output: async_p2.a, async_p2.b, async_p2.c
11670 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11673 EXPLAIN (VERBOSE, COSTS OFF)
11674 SELECT * FROM ((SELECT * FROM async_p1 WHERE b < 10) UNION ALL (SELECT * FROM async_p2 WHERE b < 10)) s WHERE CURRENT_USER = SESSION_USER;
11676 ---------------------------------------------------------------------------------
11679 Output: async_p1.a, async_p1.b, async_p1.c
11680 One-Time Filter: (CURRENT_USER = SESSION_USER)
11681 -> Foreign Scan on public.async_p1
11682 Output: async_p1.a, async_p1.b, async_p1.c
11683 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((b < 10))
11685 Output: async_p2.a, async_p2.b, async_p2.c
11686 One-Time Filter: (CURRENT_USER = SESSION_USER)
11687 -> Foreign Scan on public.async_p2
11688 Output: async_p2.a, async_p2.b, async_p2.c
11689 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((b < 10))
11692 -- Test that pending requests are processed properly
11693 SET enable_mergejoin TO false;
11694 SET enable_hashjoin TO false;
11695 EXPLAIN (VERBOSE, COSTS OFF)
11696 SELECT * FROM async_pt t1, async_p2 t2 WHERE t1.a = t2.a AND t1.b === 505;
11698 ----------------------------------------------------------------
11700 Output: t1.a, t1.b, t1.c, t2.a, t2.b, t2.c
11701 Join Filter: (t1.a = t2.a)
11703 -> Async Foreign Scan on public.async_p1 t1_1
11704 Output: t1_1.a, t1_1.b, t1_1.c
11705 Filter: (t1_1.b === 505)
11706 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11707 -> Async Foreign Scan on public.async_p2 t1_2
11708 Output: t1_2.a, t1_2.b, t1_2.c
11709 Filter: (t1_2.b === 505)
11710 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11711 -> Seq Scan on public.async_p3 t1_3
11712 Output: t1_3.a, t1_3.b, t1_3.c
11713 Filter: (t1_3.b === 505)
11715 Output: t2.a, t2.b, t2.c
11716 -> Foreign Scan on public.async_p2 t2
11717 Output: t2.a, t2.b, t2.c
11718 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11721 SELECT * FROM async_pt t1, async_p2 t2 WHERE t1.a = t2.a AND t1.b === 505;
11722 a | b | c | a | b | c
11723 ------+-----+------+------+-----+------
11724 2505 | 505 | 0505 | 2505 | 505 | 0505
11727 CREATE TABLE local_tbl (a int, b int, c text);
11728 INSERT INTO local_tbl VALUES (1505, 505, 'foo');
11730 EXPLAIN (VERBOSE, COSTS OFF)
11731 SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a;
11733 ----------------------------------------------------------------------------------------
11734 Nested Loop Left Join
11735 Output: t1.a, t1.b, t1.c, async_pt.a, async_pt.b, async_pt.c, ((InitPlan 1).col1)
11736 Join Filter: (t1.a = async_pt.a)
11741 -> Async Foreign Scan on public.async_p1 async_pt_4
11742 Remote SQL: SELECT NULL FROM public.base_tbl1 WHERE ((a < 3000))
11743 -> Async Foreign Scan on public.async_p2 async_pt_5
11744 Remote SQL: SELECT NULL FROM public.base_tbl2 WHERE ((a < 3000))
11745 -> Seq Scan on public.local_tbl t1
11746 Output: t1.a, t1.b, t1.c
11748 -> Async Foreign Scan on public.async_p1 async_pt_1
11749 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c, (InitPlan 1).col1
11750 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < 3000))
11751 -> Async Foreign Scan on public.async_p2 async_pt_2
11752 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c, (InitPlan 1).col1
11753 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a < 3000))
11756 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
11757 SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a;
11759 -----------------------------------------------------------------------------------------
11760 Nested Loop Left Join (actual rows=1 loops=1)
11761 Join Filter: (t1.a = async_pt.a)
11762 Rows Removed by Join Filter: 399
11764 -> Aggregate (actual rows=1 loops=1)
11765 -> Append (actual rows=400 loops=1)
11766 -> Async Foreign Scan on async_p1 async_pt_4 (actual rows=200 loops=1)
11767 -> Async Foreign Scan on async_p2 async_pt_5 (actual rows=200 loops=1)
11768 -> Seq Scan on local_tbl t1 (actual rows=1 loops=1)
11769 -> Append (actual rows=400 loops=1)
11770 -> Async Foreign Scan on async_p1 async_pt_1 (actual rows=200 loops=1)
11771 -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=200 loops=1)
11774 SELECT * FROM local_tbl t1 LEFT JOIN (SELECT *, (SELECT count(*) FROM async_pt WHERE a < 3000) FROM async_pt WHERE a < 3000) t2 ON t1.a = t2.a;
11775 a | b | c | a | b | c | count
11776 ------+-----+-----+------+-----+------+-------
11777 1505 | 505 | foo | 1505 | 505 | 0505 | 400
11780 EXPLAIN (VERBOSE, COSTS OFF)
11781 SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1;
11783 ----------------------------------------------------------------
11785 Output: t1.a, t1.b, t1.c
11787 -> Async Foreign Scan on public.async_p1 t1_1
11788 Output: t1_1.a, t1_1.b, t1_1.c
11789 Filter: (t1_1.b === 505)
11790 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11791 -> Async Foreign Scan on public.async_p2 t1_2
11792 Output: t1_2.a, t1_2.b, t1_2.c
11793 Filter: (t1_2.b === 505)
11794 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11795 -> Seq Scan on public.async_p3 t1_3
11796 Output: t1_3.a, t1_3.b, t1_3.c
11797 Filter: (t1_3.b === 505)
11800 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
11801 SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1;
11803 -------------------------------------------------------------------------
11804 Limit (actual rows=1 loops=1)
11805 -> Append (actual rows=1 loops=1)
11806 -> Async Foreign Scan on async_p1 t1_1 (actual rows=0 loops=1)
11807 Filter: (b === 505)
11808 -> Async Foreign Scan on async_p2 t1_2 (actual rows=0 loops=1)
11809 Filter: (b === 505)
11810 -> Seq Scan on async_p3 t1_3 (actual rows=1 loops=1)
11811 Filter: (b === 505)
11812 Rows Removed by Filter: 101
11815 SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1;
11817 ------+-----+------
11821 -- Check with foreign modify
11822 CREATE TABLE base_tbl3 (a int, b int, c text);
11823 CREATE FOREIGN TABLE remote_tbl (a int, b int, c text)
11824 SERVER loopback OPTIONS (table_name 'base_tbl3');
11825 INSERT INTO remote_tbl VALUES (2505, 505, 'bar');
11826 CREATE TABLE base_tbl4 (a int, b int, c text);
11827 CREATE FOREIGN TABLE insert_tbl (a int, b int, c text)
11828 SERVER loopback OPTIONS (table_name 'base_tbl4');
11829 EXPLAIN (VERBOSE, COSTS OFF)
11830 INSERT INTO insert_tbl (SELECT * FROM local_tbl UNION ALL SELECT * FROM remote_tbl);
11832 -------------------------------------------------------------------------
11833 Insert on public.insert_tbl
11834 Remote SQL: INSERT INTO public.base_tbl4(a, b, c) VALUES ($1, $2, $3)
11837 -> Seq Scan on public.local_tbl
11838 Output: local_tbl.a, local_tbl.b, local_tbl.c
11839 -> Async Foreign Scan on public.remote_tbl
11840 Output: remote_tbl.a, remote_tbl.b, remote_tbl.c
11841 Remote SQL: SELECT a, b, c FROM public.base_tbl3
11844 INSERT INTO insert_tbl (SELECT * FROM local_tbl UNION ALL SELECT * FROM remote_tbl);
11845 SELECT * FROM insert_tbl ORDER BY a;
11852 -- Check with direct modify
11853 EXPLAIN (VERBOSE, COSTS OFF)
11854 WITH t AS (UPDATE remote_tbl SET c = c || c RETURNING *)
11855 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;
11857 ----------------------------------------------------------------------------------------
11858 Insert on public.join_tbl
11860 -> Update on public.remote_tbl
11861 Output: remote_tbl.a, remote_tbl.b, remote_tbl.c
11862 -> Foreign Update on public.remote_tbl
11863 Remote SQL: UPDATE public.base_tbl3 SET c = (c || c) RETURNING a, b, c
11864 -> Nested Loop Left Join
11865 Output: async_pt.a, async_pt.b, async_pt.c, t.a, t.b, t.c
11866 Join Filter: ((async_pt.a = t.a) AND (async_pt.b = t.b))
11868 -> Async Foreign Scan on public.async_p1 async_pt_1
11869 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11870 Filter: (async_pt_1.b === 505)
11871 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11872 -> Async Foreign Scan on public.async_p2 async_pt_2
11873 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11874 Filter: (async_pt_2.b === 505)
11875 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11876 -> Seq Scan on public.async_p3 async_pt_3
11877 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11878 Filter: (async_pt_3.b === 505)
11880 Output: t.a, t.b, t.c
11883 WITH t AS (UPDATE remote_tbl SET c = c || c RETURNING *)
11884 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;
11885 SELECT * FROM join_tbl ORDER BY a1;
11886 a1 | b1 | c1 | a2 | b2 | c2
11887 ------+-----+------+------+-----+--------
11888 1505 | 505 | 0505 | | |
11889 2505 | 505 | 0505 | 2505 | 505 | barbar
11890 3505 | 505 | 0505 | | |
11893 DELETE FROM join_tbl;
11894 DROP TABLE local_tbl;
11895 DROP FOREIGN TABLE remote_tbl;
11896 DROP FOREIGN TABLE insert_tbl;
11897 DROP TABLE base_tbl3;
11898 DROP TABLE base_tbl4;
11899 RESET enable_mergejoin;
11900 RESET enable_hashjoin;
11901 -- Test that UPDATE/DELETE with inherited target works with async_capable enabled
11902 EXPLAIN (VERBOSE, COSTS OFF)
11903 UPDATE async_pt SET c = c || c WHERE b = 0 RETURNING *;
11905 ----------------------------------------------------------------------------------------------------------
11906 Update on public.async_pt
11907 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11908 Foreign Update on public.async_p1 async_pt_1
11909 Foreign Update on public.async_p2 async_pt_2
11910 Update on public.async_p3 async_pt_3
11912 -> Foreign Update on public.async_p1 async_pt_1
11913 Remote SQL: UPDATE public.base_tbl1 SET c = (c || c) WHERE ((b = 0)) RETURNING a, b, c
11914 -> Foreign Update on public.async_p2 async_pt_2
11915 Remote SQL: UPDATE public.base_tbl2 SET c = (c || c) WHERE ((b = 0)) RETURNING a, b, c
11916 -> Seq Scan on public.async_p3 async_pt_3
11917 Output: (async_pt_3.c || async_pt_3.c), async_pt_3.tableoid, async_pt_3.ctid, NULL::record
11918 Filter: (async_pt_3.b = 0)
11921 UPDATE async_pt SET c = c || c WHERE b = 0 RETURNING *;
11923 ------+---+----------
11924 1000 | 0 | 00000000
11925 2000 | 0 | 00000000
11926 3000 | 0 | 00000000
11929 EXPLAIN (VERBOSE, COSTS OFF)
11930 DELETE FROM async_pt WHERE b = 0 RETURNING *;
11932 ------------------------------------------------------------------------------------------
11933 Delete on public.async_pt
11934 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11935 Foreign Delete on public.async_p1 async_pt_1
11936 Foreign Delete on public.async_p2 async_pt_2
11937 Delete on public.async_p3 async_pt_3
11939 -> Foreign Delete on public.async_p1 async_pt_1
11940 Remote SQL: DELETE FROM public.base_tbl1 WHERE ((b = 0)) RETURNING a, b, c
11941 -> Foreign Delete on public.async_p2 async_pt_2
11942 Remote SQL: DELETE FROM public.base_tbl2 WHERE ((b = 0)) RETURNING a, b, c
11943 -> Seq Scan on public.async_p3 async_pt_3
11944 Output: async_pt_3.tableoid, async_pt_3.ctid
11945 Filter: (async_pt_3.b = 0)
11948 DELETE FROM async_pt WHERE b = 0 RETURNING *;
11950 ------+---+----------
11951 1000 | 0 | 00000000
11952 2000 | 0 | 00000000
11953 3000 | 0 | 00000000
11956 -- Check EXPLAIN ANALYZE for a query that scans empty partitions asynchronously
11957 DELETE FROM async_p1;
11958 DELETE FROM async_p2;
11959 DELETE FROM async_p3;
11960 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
11961 SELECT * FROM async_pt;
11963 -------------------------------------------------------------------------
11964 Append (actual rows=0 loops=1)
11965 -> Async Foreign Scan on async_p1 async_pt_1 (actual rows=0 loops=1)
11966 -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=0 loops=1)
11967 -> Seq Scan on async_p3 async_pt_3 (actual rows=0 loops=1)
11971 DROP TABLE async_pt;
11972 DROP TABLE base_tbl1;
11973 DROP TABLE base_tbl2;
11974 DROP TABLE result_tbl;
11975 DROP TABLE join_tbl;
11976 -- Test that an asynchronous fetch is processed before restarting the scan in
11977 -- ReScanForeignScan
11978 CREATE TABLE base_tbl (a int, b int);
11979 INSERT INTO base_tbl VALUES (1, 11), (2, 22), (3, 33);
11980 CREATE FOREIGN TABLE foreign_tbl (b int)
11981 SERVER loopback OPTIONS (table_name 'base_tbl');
11982 CREATE FOREIGN TABLE foreign_tbl2 () INHERITS (foreign_tbl)
11983 SERVER loopback OPTIONS (table_name 'base_tbl');
11984 EXPLAIN (VERBOSE, COSTS OFF)
11985 SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl);
11987 ---------------------------------------------------------------------------------------------------------------
11988 Seq Scan on public.base_tbl
11990 Filter: (ANY ((base_tbl.a = (SubPlan 1).col1) AND ((random() > '0'::double precision) = (SubPlan 1).col2)))
11993 Output: base_tbl.a, (random() > '0'::double precision)
11995 -> Async Foreign Scan on public.foreign_tbl foreign_tbl_1
11996 Remote SQL: SELECT NULL FROM public.base_tbl
11997 -> Async Foreign Scan on public.foreign_tbl2 foreign_tbl_2
11998 Remote SQL: SELECT NULL FROM public.base_tbl
12001 SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl);
12010 DROP FOREIGN TABLE foreign_tbl CASCADE;
12011 NOTICE: drop cascades to foreign table foreign_tbl2
12012 DROP TABLE base_tbl;
12013 ALTER SERVER loopback OPTIONS (DROP async_capable);
12014 ALTER SERVER loopback2 OPTIONS (DROP async_capable);
12015 -- ===================================================================
12016 -- test invalid server, foreign table and foreign data wrapper options
12017 -- ===================================================================
12018 -- Invalid fdw_startup_cost option
12019 CREATE SERVER inv_scst FOREIGN DATA WRAPPER postgres_fdw
12020 OPTIONS(fdw_startup_cost '100$%$#$#');
12021 ERROR: invalid value for floating point option "fdw_startup_cost": 100$%$#$#
12022 -- Invalid fdw_tuple_cost option
12023 CREATE SERVER inv_scst FOREIGN DATA WRAPPER postgres_fdw
12024 OPTIONS(fdw_tuple_cost '100$%$#$#');
12025 ERROR: invalid value for floating point option "fdw_tuple_cost": 100$%$#$#
12026 -- Invalid fetch_size option
12027 CREATE FOREIGN TABLE inv_fsz (c1 int )
12028 SERVER loopback OPTIONS (fetch_size '100$%$#$#');
12029 ERROR: invalid value for integer option "fetch_size": 100$%$#$#
12030 -- Invalid batch_size option
12031 CREATE FOREIGN TABLE inv_bsz (c1 int )
12032 SERVER loopback OPTIONS (batch_size '100$%$#$#');
12033 ERROR: invalid value for integer option "batch_size": 100$%$#$#
12034 -- No option is allowed to be specified at foreign data wrapper level
12035 ALTER FOREIGN DATA WRAPPER postgres_fdw OPTIONS (nonexistent 'fdw');
12036 ERROR: invalid option "nonexistent"
12037 HINT: There are no valid options in this context.
12038 -- ===================================================================
12039 -- test postgres_fdw.application_name GUC
12040 -- ===================================================================
12041 -- To avoid race conditions in checking the remote session's application_name,
12042 -- use this view to make the remote session itself read its application_name.
12043 CREATE VIEW my_application_name AS
12044 SELECT application_name FROM pg_stat_activity WHERE pid = pg_backend_pid();
12045 CREATE FOREIGN TABLE remote_application_name (application_name text)
12047 OPTIONS (schema_name 'public', table_name 'my_application_name');
12048 SELECT count(*) FROM remote_application_name;
12054 -- Specify escape sequences in application_name option of a server
12055 -- object so as to test that they are replaced with status information
12056 -- expectedly. Note that we are also relying on ALTER SERVER to force
12057 -- the remote session to be restarted with its new application name.
12059 -- Since pg_stat_activity.application_name may be truncated to less than
12060 -- NAMEDATALEN characters, note that substring() needs to be used
12061 -- at the condition of test query to make sure that the string consisting
12062 -- of database name and process ID is also less than that.
12063 ALTER SERVER loopback2 OPTIONS (application_name 'fdw_%d%p');
12064 SELECT count(*) FROM remote_application_name
12065 WHERE application_name =
12066 substring('fdw_' || current_database() || pg_backend_pid() for
12067 current_setting('max_identifier_length')::int);
12073 -- postgres_fdw.application_name overrides application_name option
12074 -- of a server object if both settings are present.
12075 ALTER SERVER loopback2 OPTIONS (SET application_name 'fdw_wrong');
12076 SET postgres_fdw.application_name TO 'fdw_%a%u%%';
12077 SELECT count(*) FROM remote_application_name
12078 WHERE application_name =
12079 substring('fdw_' || current_setting('application_name') ||
12080 CURRENT_USER || '%' for current_setting('max_identifier_length')::int);
12086 RESET postgres_fdw.application_name;
12087 -- Test %c (session ID) and %C (cluster name) escape sequences.
12088 ALTER SERVER loopback2 OPTIONS (SET application_name 'fdw_%C%c');
12089 SELECT count(*) FROM remote_application_name
12090 WHERE application_name =
12091 substring('fdw_' || current_setting('cluster_name') ||
12092 to_hex(trunc(EXTRACT(EPOCH FROM (SELECT backend_start FROM
12093 pg_stat_get_activity(pg_backend_pid()))))::integer) || '.' ||
12094 to_hex(pg_backend_pid())
12095 for current_setting('max_identifier_length')::int);
12102 DROP FOREIGN TABLE remote_application_name;
12103 DROP VIEW my_application_name;
12104 -- ===================================================================
12105 -- test parallel commit and parallel abort
12106 -- ===================================================================
12107 ALTER SERVER loopback OPTIONS (ADD parallel_commit 'true');
12108 ALTER SERVER loopback OPTIONS (ADD parallel_abort 'true');
12109 ALTER SERVER loopback2 OPTIONS (ADD parallel_commit 'true');
12110 ALTER SERVER loopback2 OPTIONS (ADD parallel_abort 'true');
12111 CREATE TABLE ploc1 (f1 int, f2 text);
12112 CREATE FOREIGN TABLE prem1 (f1 int, f2 text)
12113 SERVER loopback OPTIONS (table_name 'ploc1');
12114 CREATE TABLE ploc2 (f1 int, f2 text);
12115 CREATE FOREIGN TABLE prem2 (f1 int, f2 text)
12116 SERVER loopback2 OPTIONS (table_name 'ploc2');
12118 INSERT INTO prem1 VALUES (101, 'foo');
12119 INSERT INTO prem2 VALUES (201, 'bar');
12121 SELECT * FROM prem1;
12127 SELECT * FROM prem2;
12135 INSERT INTO prem1 VALUES (102, 'foofoo');
12136 INSERT INTO prem2 VALUES (202, 'barbar');
12137 RELEASE SAVEPOINT s;
12139 SELECT * FROM prem1;
12146 SELECT * FROM prem2;
12153 -- This tests executing DEALLOCATE ALL against foreign servers in parallel
12154 -- during pre-commit
12157 INSERT INTO prem1 VALUES (103, 'baz');
12158 INSERT INTO prem2 VALUES (203, 'qux');
12159 ROLLBACK TO SAVEPOINT s;
12160 RELEASE SAVEPOINT s;
12161 INSERT INTO prem1 VALUES (104, 'bazbaz');
12162 INSERT INTO prem2 VALUES (204, 'quxqux');
12164 SELECT * FROM prem1;
12172 SELECT * FROM prem2;
12181 INSERT INTO prem1 VALUES (105, 'test1');
12182 INSERT INTO prem2 VALUES (205, 'test2');
12184 SELECT * FROM prem1;
12192 SELECT * FROM prem2;
12200 -- This tests executing DEALLOCATE ALL against foreign servers in parallel
12201 -- during post-abort
12204 INSERT INTO prem1 VALUES (105, 'test1');
12205 INSERT INTO prem2 VALUES (205, 'test2');
12206 ROLLBACK TO SAVEPOINT s;
12207 RELEASE SAVEPOINT s;
12208 INSERT INTO prem1 VALUES (105, 'test1');
12209 INSERT INTO prem2 VALUES (205, 'test2');
12211 SELECT * FROM prem1;
12219 SELECT * FROM prem2;
12227 ALTER SERVER loopback OPTIONS (DROP parallel_commit);
12228 ALTER SERVER loopback OPTIONS (DROP parallel_abort);
12229 ALTER SERVER loopback2 OPTIONS (DROP parallel_commit);
12230 ALTER SERVER loopback2 OPTIONS (DROP parallel_abort);
12231 -- ===================================================================
12232 -- test for ANALYZE sampling
12233 -- ===================================================================
12234 CREATE TABLE analyze_table (id int, a text, b bigint);
12235 CREATE FOREIGN TABLE analyze_ftable (id int, a text, b bigint)
12236 SERVER loopback OPTIONS (table_name 'analyze_rtable1');
12237 INSERT INTO analyze_table (SELECT x FROM generate_series(1,1000) x);
12238 ANALYZE analyze_table;
12239 SET default_statistics_target = 10;
12240 ANALYZE analyze_table;
12241 ALTER SERVER loopback OPTIONS (analyze_sampling 'invalid');
12242 ERROR: invalid value for string option "analyze_sampling": invalid
12243 ALTER SERVER loopback OPTIONS (analyze_sampling 'auto');
12244 ANALYZE analyze_table;
12245 ALTER SERVER loopback OPTIONS (SET analyze_sampling 'system');
12246 ANALYZE analyze_table;
12247 ALTER SERVER loopback OPTIONS (SET analyze_sampling 'bernoulli');
12248 ANALYZE analyze_table;
12249 ALTER SERVER loopback OPTIONS (SET analyze_sampling 'random');
12250 ANALYZE analyze_table;
12251 ALTER SERVER loopback OPTIONS (SET analyze_sampling 'off');
12252 ANALYZE analyze_table;
12254 DROP FOREIGN TABLE analyze_ftable;
12255 DROP TABLE analyze_table;