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 -- Test CASE pushdown
1051 EXPLAIN (VERBOSE, COSTS OFF)
1052 SELECT c1,c2,c3 FROM ft2 WHERE CASE WHEN c1 > 990 THEN c1 END < 1000 ORDER BY c1;
1054 ----------------------------------------------------------------------------------------------------------------------------------------------------------------
1055 Foreign Scan on public.ft2
1057 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
1060 SELECT c1,c2,c3 FROM ft2 WHERE CASE WHEN c1 > 990 THEN c1 END < 1000 ORDER BY c1;
1075 EXPLAIN (VERBOSE, COSTS OFF)
1076 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;
1078 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1079 Foreign Scan on public.ft2
1081 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
1084 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;
1090 EXPLAIN (VERBOSE, COSTS OFF)
1091 SELECT * FROM ft1 WHERE c1 > (CASE mod(c1, 4) WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END);
1093 ----------------------------------------------------------------------------------------------------------------------------------------------------------
1094 Foreign Scan on public.ft1
1095 Output: c1, c2, c3, c4, c5, c6, c7, c8
1096 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)))
1099 -- CASE cannot be pushed down because of unshippable arg clause
1100 EXPLAIN (VERBOSE, COSTS OFF)
1101 SELECT * FROM ft1 WHERE c1 > (CASE random()::integer WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END);
1103 -----------------------------------------------------------------------------------------
1104 Foreign Scan on public.ft1
1105 Output: c1, c2, c3, c4, c5, c6, c7, c8
1106 Filter: (ft1.c1 > CASE (random())::integer WHEN 0 THEN 1 WHEN 2 THEN 50 ELSE 100 END)
1107 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1110 -- these are shippable
1111 EXPLAIN (VERBOSE, COSTS OFF)
1112 SELECT * FROM ft1 WHERE CASE c6 WHEN 'foo' THEN true ELSE c3 < 'bar' 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 ((CASE c6 WHEN 'foo'::text THEN true ELSE (c3 < 'bar') END))
1120 EXPLAIN (VERBOSE, COSTS OFF)
1121 SELECT * FROM ft1 WHERE CASE c3 WHEN c6 THEN true ELSE c3 < 'bar' END;
1123 -----------------------------------------------------------------------------------------------------------------------------------
1124 Foreign Scan on public.ft1
1125 Output: c1, c2, c3, c4, c5, c6, c7, c8
1126 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))
1129 -- but this is not because of collation
1130 EXPLAIN (VERBOSE, COSTS OFF)
1131 SELECT * FROM ft1 WHERE CASE c3 COLLATE "C" WHEN c6 THEN true ELSE c3 < 'bar' END;
1133 -------------------------------------------------------------------------------------
1134 Foreign Scan on public.ft1
1135 Output: c1, c2, c3, c4, c5, c6, c7, c8
1136 Filter: CASE (ft1.c3)::text WHEN ft1.c6 THEN true ELSE (ft1.c3 < 'bar'::text) END
1137 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1140 -- a regconfig constant referring to this text search configuration
1141 -- is initially unshippable
1142 CREATE TEXT SEARCH CONFIGURATION public.custom_search
1143 (COPY = pg_catalog.english);
1144 EXPLAIN (VERBOSE, COSTS OFF)
1145 SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1
1146 WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0;
1148 -------------------------------------------------------------------------
1149 Foreign Scan on public.ft1
1150 Output: c1, to_tsvector('custom_search'::regconfig, c3)
1151 Filter: (length(to_tsvector('custom_search'::regconfig, ft1.c3)) > 0)
1152 Remote SQL: SELECT "C 1", c3 FROM "S 1"."T 1" WHERE (("C 1" = 642))
1155 SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1
1156 WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0;
1162 -- but if it's in a shippable extension, it can be shipped
1163 ALTER EXTENSION postgres_fdw ADD TEXT SEARCH CONFIGURATION public.custom_search;
1164 -- however, that doesn't flush the shippability cache, so do a quick reconnect
1166 EXPLAIN (VERBOSE, COSTS OFF)
1167 SELECT c1, to_tsvector('custom_search'::regconfig, c3) FROM ft1
1168 WHERE c1 = 642 AND length(to_tsvector('custom_search'::regconfig, c3)) > 0;
1170 ----------------------------------------------------------------------------------------------------------------------------------------------
1171 Foreign Scan on public.ft1
1172 Output: c1, to_tsvector('custom_search'::regconfig, c3)
1173 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))
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 -- ===================================================================
1185 -- ===================================================================
1186 -- we should not push order by clause with volatile expressions or unsafe
1188 EXPLAIN (VERBOSE, COSTS OFF)
1189 SELECT * FROM ft2 ORDER BY ft2.c1, random();
1191 -------------------------------------------------------------------------------
1193 Output: c1, c2, c3, c4, c5, c6, c7, c8, (random())
1194 Sort Key: ft2.c1, (random())
1195 -> Foreign Scan on public.ft2
1196 Output: c1, c2, c3, c4, c5, c6, c7, c8, random()
1197 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1200 EXPLAIN (VERBOSE, COSTS OFF)
1201 SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C";
1203 -------------------------------------------------------------------------------
1205 Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text)
1206 Sort Key: ft2.c1, ft2.c3 COLLATE "C"
1207 -> Foreign Scan on public.ft2
1208 Output: c1, c2, c3, c4, c5, c6, c7, c8, c3
1209 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1212 -- Ensure we don't push ORDER BY expressions which are Consts at the UNION
1213 -- child level to the foreign server.
1214 EXPLAIN (VERBOSE, COSTS OFF)
1216 SELECT 1 AS type,c1 FROM ft1
1218 SELECT 2 AS type,c1 FROM ft2
1219 ) a ORDER BY type,c1;
1221 ---------------------------------------------------------------------------------
1223 Sort Key: (1), ft1.c1
1224 -> Foreign Scan on public.ft1
1226 Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1227 -> Foreign Scan on public.ft2
1229 Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1232 EXPLAIN (VERBOSE, COSTS OFF)
1234 SELECT 1 AS type,c1 FROM ft1
1236 SELECT 2 AS type,c1 FROM ft2
1239 ---------------------------------------------------
1242 -> Foreign Scan on public.ft1
1244 Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
1245 -> Foreign Scan on public.ft2
1247 Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
1250 -- ===================================================================
1252 -- ===================================================================
1253 -- Analyze ft4 and ft5 so that we have better statistics. These tables do not
1254 -- have use_remote_estimate set.
1258 EXPLAIN (VERBOSE, COSTS OFF)
1259 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;
1261 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1263 Output: t1.c1, t2.c1, t1.c3
1264 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1265 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
1268 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;
1283 -- join three tables
1284 EXPLAIN (VERBOSE, COSTS OFF)
1285 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;
1287 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1289 Output: t1.c1, t2.c2, t3.c3, t1.c3
1290 Relations: ((public.ft1 t1) INNER JOIN (public.ft2 t2)) INNER JOIN (public.ft4 t3)
1291 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
1294 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;
1310 EXPLAIN (VERBOSE, COSTS OFF)
1311 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;
1313 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1315 Output: t1.c1, t2.c1
1316 Relations: (public.ft4 t1) LEFT JOIN (public.ft5 t2)
1317 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
1320 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;
1335 -- left outer join three tables
1336 EXPLAIN (VERBOSE, COSTS OFF)
1337 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;
1339 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1341 Output: t1.c1, t2.c2, t3.c3
1342 Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
1343 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
1346 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;
1361 -- left outer join + placement of clauses.
1362 -- clauses within the nullable side are not pulled up, but top level clause on
1363 -- non-nullable side is pushed into non-nullable side
1364 EXPLAIN (VERBOSE, COSTS OFF)
1365 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;
1367 ---------------------------------------------------------------------------------------------------------------------------------------------------------------
1369 Output: t1.c1, t1.c2, ft5.c1, ft5.c2
1370 Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
1371 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))
1374 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;
1383 -- clauses within the nullable side are not pulled up, but the top level clause
1384 -- on nullable side is not pushed down into 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)
1387 WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
1389 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1391 Output: t1.c1, t1.c2, ft5.c1, ft5.c2
1392 Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
1393 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))
1396 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)
1397 WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
1407 EXPLAIN (VERBOSE, COSTS OFF)
1408 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;
1410 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1412 Output: t1.c1, t2.c1
1413 Relations: (public.ft4 t2) LEFT JOIN (public.ft5 t1)
1414 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
1417 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;
1432 -- right outer join three tables
1433 EXPLAIN (VERBOSE, COSTS OFF)
1434 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;
1436 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1438 Output: t1.c1, t2.c2, t3.c3
1439 Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
1440 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
1443 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;
1459 EXPLAIN (VERBOSE, COSTS OFF)
1460 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;
1462 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1464 Output: t1.c1, t2.c1
1465 Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
1466 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
1469 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;
1484 -- full outer join with restrictions on the joining relations
1485 -- a. the joining relations are both base relations
1486 EXPLAIN (VERBOSE, COSTS OFF)
1487 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;
1489 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1491 Output: ft4.c1, ft5.c1
1492 Relations: (public.ft4) FULL JOIN (public.ft5)
1493 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
1496 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;
1509 EXPLAIN (VERBOSE, COSTS OFF)
1510 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;
1512 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1515 Relations: (public.ft4) FULL JOIN (public.ft5)
1516 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
1519 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;
1534 -- b. one of the joining relations is a base relation and the other is a join
1536 EXPLAIN (VERBOSE, COSTS OFF)
1537 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;
1539 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1541 Output: ft4.c1, t2.c1, t3.c1
1542 Relations: (public.ft4) FULL JOIN ((public.ft4 t2) LEFT JOIN (public.ft5 t3))
1543 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
1546 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;
1557 -- c. test deparsing the remote query as nested subqueries
1558 EXPLAIN (VERBOSE, COSTS OFF)
1559 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;
1561 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1563 Output: ft4.c1, ft4_1.c1, ft5.c1
1564 Relations: (public.ft4) FULL JOIN ((public.ft4 ft4_1) FULL JOIN (public.ft5))
1565 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
1568 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;
1581 -- d. test deparsing rowmarked relations as subqueries
1582 EXPLAIN (VERBOSE, COSTS OFF)
1583 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;
1585 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1587 Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".ctid, ft4.*, ft5.*
1589 Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".ctid, ft4.*, ft5.*
1591 Output: ft4.c1, ft4.*, ft5.c1, ft5.*
1592 Relations: (public.ft4) FULL JOIN (public.ft5)
1593 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
1595 Output: ft4.c1, ft4.*, ft5.c1, ft5.*
1596 Sort Key: ft4.c1, ft5.c1
1598 Output: ft4.c1, ft4.*, ft5.c1, ft5.*
1599 Hash Cond: (ft4.c1 = ft5.c1)
1600 Filter: ((ft4.c1 IS NULL) OR (ft4.c1 IS NOT NULL))
1601 -> Foreign Scan on public.ft4
1602 Output: ft4.c1, ft4.*
1603 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))
1605 Output: ft5.c1, ft5.*
1606 -> Foreign Scan on public.ft5
1607 Output: ft5.c1, ft5.*
1608 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))
1610 Output: "T 3".c1, "T 3".ctid
1611 -> Seq Scan on "S 1"."T 3"
1612 Output: "T 3".c1, "T 3".ctid
1613 Filter: ("T 3".c1 = 50)
1616 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;
1629 -- full outer join + inner join
1630 EXPLAIN (VERBOSE, COSTS OFF)
1631 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;
1633 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1635 Output: t1.c1, t2.c1, t3.c1
1636 Relations: ((public.ft4 t1) INNER JOIN (public.ft5 t2)) FULL JOIN (public.ft4 t3)
1637 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
1640 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;
1655 -- full outer join three tables
1656 EXPLAIN (VERBOSE, COSTS OFF)
1657 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;
1659 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1661 Output: t1.c1, t2.c2, t3.c3
1662 Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
1663 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
1666 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;
1681 -- full outer join + right outer join
1682 EXPLAIN (VERBOSE, COSTS OFF)
1683 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;
1685 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1687 Output: t1.c1, t2.c2, t3.c3
1688 Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
1689 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
1692 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;
1707 -- right outer join + full outer join
1708 EXPLAIN (VERBOSE, COSTS OFF)
1709 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;
1711 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1713 Output: t1.c1, t2.c2, t3.c3
1714 Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) FULL JOIN (public.ft4 t3)
1715 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
1718 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;
1733 -- full outer join + left outer join
1734 EXPLAIN (VERBOSE, COSTS OFF)
1735 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;
1737 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1739 Output: t1.c1, t2.c2, t3.c3
1740 Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
1741 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
1744 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;
1759 -- left outer join + full outer join
1760 EXPLAIN (VERBOSE, COSTS OFF)
1761 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;
1763 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1765 Output: t1.c1, t2.c2, t3.c3
1766 Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
1767 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
1770 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;
1785 SET enable_memoize TO off;
1786 -- right outer join + left outer join
1787 EXPLAIN (VERBOSE, COSTS OFF)
1788 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;
1790 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1792 Output: t1.c1, t2.c2, t3.c3
1793 Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) LEFT JOIN (public.ft4 t3)
1794 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
1797 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;
1812 RESET enable_memoize;
1813 -- left outer join + right outer join
1814 EXPLAIN (VERBOSE, COSTS OFF)
1815 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;
1817 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1819 Output: t1.c1, t2.c2, t3.c3
1820 Relations: (public.ft4 t3) LEFT JOIN ((public.ft2 t1) INNER JOIN (public.ft2 t2))
1821 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
1824 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;
1839 -- full outer join + WHERE clause, only matched rows
1840 EXPLAIN (VERBOSE, COSTS OFF)
1841 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;
1843 ------------------------------------------------------------------------------------------------------------------------------------------------------------------
1845 Output: t1.c1, t2.c1
1847 Output: t1.c1, t2.c1
1848 Sort Key: t1.c1, t2.c1
1850 Output: t1.c1, t2.c1
1851 Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
1852 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)))
1855 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;
1870 -- full outer join + WHERE clause with shippable extensions set
1871 EXPLAIN (VERBOSE, COSTS OFF)
1872 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;
1874 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1876 Output: t1.c1, t2.c2, t1.c3
1877 Relations: (public.ft1 t1) FULL JOIN (public.ft2 t2)
1878 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
1881 ALTER SERVER loopback OPTIONS (DROP extensions);
1882 -- full outer join + WHERE clause with shippable extensions not set
1883 EXPLAIN (VERBOSE, COSTS OFF)
1884 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;
1886 -------------------------------------------------------------------------------------------------------------------------------
1888 Output: t1.c1, t2.c2, t1.c3
1890 Output: t1.c1, t2.c2, t1.c3
1891 Filter: (postgres_fdw_abs(t1.c1) > 0)
1892 Relations: (public.ft1 t1) FULL JOIN (public.ft2 t2)
1893 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"))))
1896 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
1897 -- join two tables with FOR UPDATE clause
1898 -- tests whole-row reference for row marks
1899 EXPLAIN (VERBOSE, COSTS OFF)
1900 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;
1902 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1904 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1905 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1906 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
1909 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;
1924 EXPLAIN (VERBOSE, COSTS OFF)
1925 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;
1927 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1929 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1930 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1931 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
1934 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;
1949 -- join two tables with FOR SHARE clause
1950 EXPLAIN (VERBOSE, COSTS OFF)
1951 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;
1953 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1955 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1956 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1957 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
1960 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;
1975 EXPLAIN (VERBOSE, COSTS OFF)
1976 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;
1978 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1980 Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1981 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1982 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
1985 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;
2001 EXPLAIN (VERBOSE, COSTS OFF)
2002 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;
2004 -------------------------------------------------------------------------------------------------------------------------------------
2006 Output: t.c1_1, t.c2_1, t.c1_3
2009 Output: t1.c1, t1.c3, t2.c1
2010 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2011 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"))))
2013 Output: t.c1_1, t.c2_1, t.c1_3
2014 Sort Key: t.c1_3, t.c1_1
2016 Output: t.c1_1, t.c2_1, t.c1_3
2019 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;
2034 -- ctid with whole-row reference
2035 EXPLAIN (VERBOSE, COSTS OFF)
2036 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;
2038 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2040 Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
2041 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2042 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
2046 EXPLAIN (VERBOSE, COSTS OFF)
2047 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;
2049 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2052 Relations: (public.ft1 t1) SEMI JOIN (public.ft2 t2)
2053 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
2056 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;
2071 -- ANTI JOIN, not pushed down
2072 EXPLAIN (VERBOSE, COSTS OFF)
2073 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;
2075 ---------------------------------------------------------------------------------------
2080 Merge Cond: (t1.c1 = t2.c2)
2081 -> Foreign Scan on public.ft1 t1
2083 Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
2084 -> Foreign Scan on public.ft2 t2
2086 Remote SQL: SELECT c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
2089 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;
2104 -- CROSS JOIN can be pushed down
2105 EXPLAIN (VERBOSE, COSTS OFF)
2106 SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
2108 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2110 Output: t1.c1, t2.c1
2111 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2112 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
2115 SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
2130 -- different server, not pushed down. No result expected.
2131 EXPLAIN (VERBOSE, COSTS OFF)
2132 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;
2134 ---------------------------------------------------------------------------------------
2136 Output: t1.c1, t2.c1
2138 Output: t1.c1, t2.c1
2139 Merge Cond: (t2.c1 = t1.c1)
2140 -> Foreign Scan on public.ft6 t2
2141 Output: t2.c1, t2.c2, t2.c3
2142 Remote SQL: SELECT c1 FROM "S 1"."T 4" ORDER BY c1 ASC NULLS LAST
2144 Output: t1.c1, t1.c2, t1.c3
2145 -> Foreign Scan on public.ft5 t1
2146 Output: t1.c1, t1.c2, t1.c3
2147 Remote SQL: SELECT c1 FROM "S 1"."T 4" ORDER BY c1 ASC NULLS LAST
2150 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 -- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS
2156 -- JOIN since c8 in both tables has same value.
2157 EXPLAIN (VERBOSE, COSTS OFF)
2158 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;
2160 -------------------------------------------------------------------------
2162 Output: t1.c1, t2.c1
2164 Output: t1.c1, t2.c1
2165 Sort Key: t1.c1, t2.c1
2167 Output: t1.c1, t2.c1
2168 Merge Cond: (t1.c8 = t2.c8)
2170 Output: t1.c1, t1.c8
2172 -> Foreign Scan on public.ft1 t1
2173 Output: t1.c1, t1.c8
2174 Remote SQL: SELECT "C 1", c8 FROM "S 1"."T 1"
2176 Output: t2.c1, t2.c8
2178 -> Foreign Scan on public.ft2 t2
2179 Output: t2.c1, t2.c8
2180 Remote SQL: SELECT "C 1", c8 FROM "S 1"."T 1"
2183 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;
2198 -- unsafe conditions on one side (c8 has a UDT), not pushed down.
2199 EXPLAIN (VERBOSE, COSTS OFF)
2200 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;
2202 -----------------------------------------------------------------------------
2204 Output: t1.c1, t2.c1, t1.c3
2206 Output: t1.c1, t2.c1, t1.c3
2207 Sort Key: t1.c3, t1.c1
2209 Output: t1.c1, t2.c1, t1.c3
2210 Hash Cond: (t2.c1 = t1.c1)
2211 -> Foreign Scan on public.ft2 t2
2213 Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2215 Output: t1.c1, t1.c3
2216 -> Foreign Scan on public.ft1 t1
2217 Output: t1.c1, t1.c3
2218 Filter: (t1.c8 = 'foo'::user_enum)
2219 Remote SQL: SELECT "C 1", c3, c8 FROM "S 1"."T 1"
2222 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;
2237 -- join where unsafe to pushdown condition in WHERE clause has a column not
2238 -- in the SELECT clause. In this test unsafe clause needs to have column
2239 -- references from both joining sides so that the clause is not pushed down
2240 -- into one of the joining sides.
2241 EXPLAIN (VERBOSE, COSTS OFF)
2242 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;
2244 -------------------------------------------------------------------------------------------------------------------------------------------------------
2246 Output: t1.c1, t2.c1, t1.c3
2248 Output: t1.c1, t2.c1, t1.c3
2249 Sort Key: t1.c3, t1.c1
2251 Output: t1.c1, t2.c1, t1.c3
2252 Filter: (t1.c8 = t2.c8)
2253 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2254 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"))))
2257 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;
2272 -- Aggregate after UNION, for testing setrefs
2273 EXPLAIN (VERBOSE, COSTS OFF)
2274 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;
2276 ----------------------------------------------------------------------------------------------------------------------------------------------------
2278 Output: t1.c1, (avg((t1.c1 + t2.c1)))
2280 Output: t1.c1, (avg((t1.c1 + t2.c1)))
2283 Output: t1.c1, avg((t1.c1 + t2.c1))
2286 Output: t1.c1, t2.c1
2287 Group Key: t1.c1, t2.c1
2290 Output: t1.c1, t2.c1
2291 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2292 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"))))
2294 Output: t1_1.c1, t2_1.c1
2295 Relations: (public.ft1 t1_1) INNER JOIN (public.ft2 t2_1)
2296 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"))))
2299 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;
2301 ------+----------------------
2302 101 | 202.0000000000000000
2303 102 | 204.0000000000000000
2304 103 | 206.0000000000000000
2305 104 | 208.0000000000000000
2306 105 | 210.0000000000000000
2307 106 | 212.0000000000000000
2308 107 | 214.0000000000000000
2309 108 | 216.0000000000000000
2310 109 | 218.0000000000000000
2311 110 | 220.0000000000000000
2314 -- join with lateral reference
2315 EXPLAIN (VERBOSE, COSTS OFF)
2316 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;
2318 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2323 -> Index Scan using t1_pkey on "S 1"."T 1" t1
2324 Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
2328 -> Subquery Scan on q
2330 Output: t2.c1, t3.c1
2333 Output: t2.c1, t3.c1
2334 Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
2335 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))))
2338 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;
2353 -- join with pseudoconstant quals
2354 EXPLAIN (VERBOSE, COSTS OFF)
2355 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;
2357 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2359 Output: t1.c1, t2.c1, t1.c3
2361 Output: t1.c1, t2.c1, t1.c3
2362 One-Time Filter: (CURRENT_USER = SESSION_USER)
2364 Output: t1.c1, t1.c3, t2.c1
2365 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2366 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
2369 -- non-Var items in targetlist of the nullable rel of a join preventing
2370 -- push-down in some cases
2371 -- unable to push {ft1, ft2}
2372 EXPLAIN (VERBOSE, COSTS OFF)
2373 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;
2375 ---------------------------------------------------------------------------------------------------------------------------
2376 Nested Loop Left Join
2377 Output: (13), ft2.c1
2378 Join Filter: (13 = ft2.c1)
2379 -> Foreign Scan on public.ft2
2381 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
2384 -> Foreign Scan on public.ft1
2386 Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE (("C 1" = 13))
2389 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;
2400 -- ok to push {ft1, ft2} but not {ft1, ft2, ft4}
2401 EXPLAIN (VERBOSE, COSTS OFF)
2402 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;
2404 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2405 Nested Loop Left Join
2406 Output: ft4.c1, (13), ft1.c1, ft2.c1
2407 Join Filter: (ft4.c1 = ft1.c1)
2408 -> Foreign Scan on public.ft4
2409 Output: ft4.c1, ft4.c2, ft4.c3
2410 Remote SQL: SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 10)) AND ((c1 <= 15))
2412 Output: ft1.c1, ft2.c1, (13)
2414 Output: ft1.c1, ft2.c1, 13
2415 Relations: (public.ft1) INNER JOIN (public.ft2)
2416 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
2419 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;
2427 -- join with nullable side with some columns with null values
2428 UPDATE ft5 SET c3 = null where c1 % 9 = 0;
2429 EXPLAIN (VERBOSE, COSTS OFF)
2430 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;
2432 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2434 Output: ft5.*, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2
2435 Relations: (public.ft5) INNER JOIN (public.ft4)
2436 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
2439 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;
2440 ft5 | c1 | c2 | c3 | c1 | c2
2441 ----------------+----+----+--------+----+----
2442 (12,13,AAA012) | 12 | 13 | AAA012 | 12 | 13
2443 (18,19,) | 18 | 19 | | 18 | 19
2444 (24,25,AAA024) | 24 | 25 | AAA024 | 24 | 25
2445 (30,31,AAA030) | 30 | 31 | AAA030 | 30 | 31
2448 -- multi-way join involving multiple merge joins
2449 -- (this case used to have EPQ-related planning problems)
2450 CREATE TABLE local_tbl (c1 int NOT NULL, c2 int NOT NULL, c3 text, CONSTRAINT local_tbl_pkey PRIMARY KEY (c1));
2451 INSERT INTO local_tbl SELECT id, id % 10, to_char(id, 'FM0000') FROM generate_series(1, 1000) id;
2453 SET enable_nestloop TO false;
2454 SET enable_hashjoin TO false;
2455 EXPLAIN (VERBOSE, COSTS OFF)
2456 SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1
2457 AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE;
2459 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2461 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
2463 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
2465 Merge Cond: (ft1.c2 = local_tbl.c1)
2467 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.*
2468 Relations: (((public.ft1) INNER JOIN (public.ft2)) INNER JOIN (public.ft4)) INNER JOIN (public.ft5)
2469 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
2471 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.*
2472 Merge Cond: (ft1.c2 = ft5.c1)
2474 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.*
2475 Merge Cond: (ft1.c2 = ft4.c1)
2477 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.*
2480 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.*
2481 Merge Cond: (ft1.c1 = ft2.c1)
2483 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2485 -> Foreign Scan on public.ft1
2486 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2487 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 100)) FOR UPDATE
2489 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*
2490 -> Foreign Scan on public.ft2
2491 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*
2492 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
2494 Output: ft4.c1, ft4.c2, ft4.c3, ft4.*
2496 -> Foreign Scan on public.ft4
2497 Output: ft4.c1, ft4.c2, ft4.c3, ft4.*
2498 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3" FOR UPDATE
2500 Output: ft5.c1, ft5.c2, ft5.c3, ft5.*
2502 -> Foreign Scan on public.ft5
2503 Output: ft5.c1, ft5.c2, ft5.c3, ft5.*
2504 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4" FOR UPDATE
2505 -> Index Scan using local_tbl_pkey on public.local_tbl
2506 Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid
2509 SELECT * FROM ft1, ft2, ft4, ft5, local_tbl WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1
2510 AND ft1.c2 = ft5.c1 AND ft1.c2 = local_tbl.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE;
2511 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
2512 ----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------+----+----+--------+----+----+------
2513 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
2514 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
2515 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
2516 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
2517 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
2518 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
2519 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
2520 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
2521 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
2522 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
2525 RESET enable_nestloop;
2526 RESET enable_hashjoin;
2527 -- test that add_paths_with_pathkeys_for_rel() arranges for the epq_path to
2528 -- return columns needed by the parent ForeignScan node
2529 EXPLAIN (VERBOSE, COSTS OFF)
2530 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;
2532 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2534 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.*
2536 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.*
2537 Merge Cond: (local_tbl.c1 = ft1.c1)
2538 -> Index Scan using local_tbl_pkey on public.local_tbl
2539 Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid
2541 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))
2543 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)
2544 Relations: (public.ft1) INNER JOIN (public.ft2)
2545 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
2547 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, ft2.c3
2549 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
2552 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
2553 Hash Cond: (ft1.c1 = ft2.c1)
2554 -> Foreign Scan on public.ft1
2555 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2556 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 100))
2558 Output: ft2.*, ft2.c1, ft2.c3
2559 -> Foreign Scan on public.ft2
2560 Output: ft2.*, ft2.c1, ft2.c3
2561 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
2564 ALTER SERVER loopback OPTIONS (DROP extensions);
2565 ALTER SERVER loopback OPTIONS (ADD fdw_startup_cost '10000.0');
2566 EXPLAIN (VERBOSE, COSTS OFF)
2567 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;
2569 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2571 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.*
2572 -> Nested Loop Left Join
2573 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.*
2574 Join Filter: (local_tbl.c3 = ft1.c3)
2575 -> Index Scan using local_tbl_pkey on public.local_tbl
2576 Output: local_tbl.c1, local_tbl.c2, local_tbl.c3, local_tbl.ctid
2578 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*
2580 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*
2581 Filter: ((ft1.c1 - postgres_fdw_abs(ft2.c2)) = 0)
2582 Relations: (public.ft1) INNER JOIN (public.ft2)
2583 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
2585 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, ft2.c2
2588 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*, ft2.*, ft2.c2
2589 Merge Cond: (ft1.c1 = ft2.c1)
2590 Join Filter: ((ft1.c1 - postgres_fdw_abs(ft2.c2)) = 0)
2592 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2594 -> Foreign Scan on public.ft1
2595 Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2596 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 100))
2598 Output: ft2.*, ft2.c1, ft2.c2
2599 -> Foreign Scan on public.ft2
2600 Output: ft2.*, ft2.c1, ft2.c2
2601 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
2604 ALTER SERVER loopback OPTIONS (DROP fdw_startup_cost);
2605 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
2606 DROP TABLE local_tbl;
2607 -- check join pushdown in situations where multiple userids are involved
2608 CREATE ROLE regress_view_owner SUPERUSER;
2609 CREATE USER MAPPING FOR regress_view_owner SERVER loopback;
2610 GRANT SELECT ON ft4 TO regress_view_owner;
2611 GRANT SELECT ON ft5 TO regress_view_owner;
2612 CREATE VIEW v4 AS SELECT * FROM ft4;
2613 CREATE VIEW v5 AS SELECT * FROM ft5;
2614 ALTER VIEW v5 OWNER TO regress_view_owner;
2615 EXPLAIN (VERBOSE, COSTS OFF)
2616 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
2618 ----------------------------------------------------------------------
2620 Output: ft4.c1, ft5.c2, ft5.c1
2622 Output: ft4.c1, ft5.c2, ft5.c1
2623 Sort Key: ft4.c1, ft5.c1
2625 Output: ft4.c1, ft5.c2, ft5.c1
2626 Hash Cond: (ft4.c1 = ft5.c1)
2627 -> Foreign Scan on public.ft4
2628 Output: ft4.c1, ft4.c2, ft4.c3
2629 Remote SQL: SELECT c1 FROM "S 1"."T 3"
2631 Output: ft5.c2, ft5.c1
2632 -> Foreign Scan on public.ft5
2633 Output: ft5.c2, ft5.c1
2634 Remote SQL: SELECT c1, c2 FROM "S 1"."T 4"
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;
2652 ALTER VIEW v4 OWNER TO regress_view_owner;
2653 EXPLAIN (VERBOSE, COSTS OFF)
2654 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
2656 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2658 Output: ft4.c1, ft5.c2, ft5.c1
2659 Relations: (public.ft4) LEFT JOIN (public.ft5)
2660 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
2663 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;
2678 EXPLAIN (VERBOSE, COSTS OFF)
2679 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
2681 ----------------------------------------------------------------------
2683 Output: ft4.c1, t2.c2, t2.c1
2685 Output: ft4.c1, t2.c2, t2.c1
2686 Sort Key: ft4.c1, t2.c1
2688 Output: ft4.c1, t2.c2, t2.c1
2689 Hash Cond: (ft4.c1 = t2.c1)
2690 -> Foreign Scan on public.ft4
2691 Output: ft4.c1, ft4.c2, ft4.c3
2692 Remote SQL: SELECT c1 FROM "S 1"."T 3"
2694 Output: t2.c2, t2.c1
2695 -> Foreign Scan on public.ft5 t2
2696 Output: t2.c2, t2.c1
2697 Remote SQL: SELECT c1, c2 FROM "S 1"."T 4"
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;
2715 ALTER VIEW v4 OWNER TO CURRENT_USER;
2716 EXPLAIN (VERBOSE, COSTS OFF)
2717 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
2719 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2721 Output: ft4.c1, t2.c2, t2.c1
2722 Relations: (public.ft4) LEFT JOIN (public.ft5 t2)
2723 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
2726 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;
2741 ALTER VIEW v4 OWNER TO regress_view_owner;
2742 -- Make sure this big CROSS JOIN query is pushed down
2743 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 CROSS JOIN ft2 CROSS JOIN ft4 CROSS JOIN ft5;
2745 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------
2748 Relations: Aggregate on ((((public.ft1) INNER JOIN (public.ft2)) INNER JOIN (public.ft4)) INNER JOIN (public.ft5))
2749 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))
2752 -- Make sure query cancellation works
2754 SET LOCAL statement_timeout = '10ms';
2755 select count(*) from ft1 CROSS JOIN ft2 CROSS JOIN ft4 CROSS JOIN ft5; -- this takes very long
2756 ERROR: canceling statement due to statement timeout
2758 -- ====================================================================
2759 -- Check that userid to use when querying the remote table is correctly
2760 -- propagated into foreign rels present in subqueries under an UNION ALL
2761 -- ====================================================================
2762 CREATE ROLE regress_view_owner_another;
2763 ALTER VIEW v4 OWNER TO regress_view_owner_another;
2764 GRANT SELECT ON ft4 TO regress_view_owner_another;
2765 ALTER FOREIGN TABLE ft4 OPTIONS (ADD use_remote_estimate 'true');
2766 -- The following should query the remote backing table of ft4 as user
2767 -- regress_view_owner_another, the view owner, though it fails as expected
2768 -- due to the lack of a user mapping for that user.
2769 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM v4;
2770 ERROR: user mapping not found for user "regress_view_owner_another", server "loopback"
2771 -- Likewise, but with the query under an UNION ALL
2772 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM (SELECT * FROM v4 UNION ALL SELECT * FROM v4);
2773 ERROR: user mapping not found for user "regress_view_owner_another", server "loopback"
2774 -- Should not get that error once a user mapping is created
2775 CREATE USER MAPPING FOR regress_view_owner_another SERVER loopback OPTIONS (password_required 'false');
2776 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM v4;
2778 --------------------------------------------------
2779 Foreign Scan on public.ft4
2780 Output: ft4.c1, ft4.c2, ft4.c3
2781 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
2784 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM (SELECT * FROM v4 UNION ALL SELECT * FROM v4);
2786 --------------------------------------------------------
2788 -> Foreign Scan on public.ft4
2789 Output: ft4.c1, ft4.c2, ft4.c3
2790 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
2791 -> Foreign Scan on public.ft4 ft4_1
2792 Output: ft4_1.c1, ft4_1.c2, ft4_1.c3
2793 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
2796 DROP USER MAPPING FOR regress_view_owner_another SERVER loopback;
2797 DROP OWNED BY regress_view_owner_another;
2798 DROP ROLE regress_view_owner_another;
2799 ALTER FOREIGN TABLE ft4 OPTIONS (SET use_remote_estimate 'false');
2801 DROP OWNED BY regress_view_owner;
2802 DROP ROLE regress_view_owner;
2803 -- ===================================================================
2804 -- Aggregate and grouping queries
2805 -- ===================================================================
2806 -- Simple aggregates
2807 explain (verbose, costs off)
2808 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;
2810 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2812 Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2
2813 Relations: Aggregate on (public.ft1)
2814 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
2817 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;
2818 count | sum | avg | min | max | stddev | sum2
2819 -------+-------+----------------------+-----+------+--------+-------
2820 100 | 49600 | 496.0000000000000000 | 1 | 991 | 0 | 49600
2821 100 | 49700 | 497.0000000000000000 | 2 | 992 | 0 | 49700
2822 100 | 49800 | 498.0000000000000000 | 3 | 993 | 0 | 49800
2823 100 | 49900 | 499.0000000000000000 | 4 | 994 | 0 | 49900
2824 100 | 50500 | 505.0000000000000000 | 0 | 1000 | 0 | 50500
2827 explain (verbose, costs off)
2828 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;
2830 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2832 Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2
2833 Relations: Aggregate on (public.ft1)
2834 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
2837 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;
2838 count | sum | avg | min | max | stddev | sum2
2839 -------+-------+----------------------+-----+-----+--------+-------
2840 100 | 49600 | 496.0000000000000000 | 1 | 991 | 0 | 49600
2843 -- Aggregate is not pushed down as aggregation contains random()
2844 explain (verbose, costs off)
2845 select sum(c1 * (random() <= 1)::int) as sum, avg(c1) from ft1;
2847 -------------------------------------------------------------------------------
2849 Output: sum((c1 * ((random() <= '1'::double precision))::integer)), avg(c1)
2850 -> Foreign Scan on public.ft1
2852 Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2855 -- Aggregate over join query
2856 explain (verbose, costs off)
2857 select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6;
2859 --------------------------------------------------------------------------------------------------------------------------------------------------
2861 Output: (count(*)), (sum(t1.c1)), (avg(t2.c1))
2862 Relations: Aggregate on ((public.ft1 t1) INNER JOIN (public.ft1 t2))
2863 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))))
2866 select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6;
2868 -------+---------+----------------------
2869 10000 | 5010000 | 501.0000000000000000
2872 -- Not pushed down due to local conditions present in underneath input rel
2873 explain (verbose, costs off)
2874 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;
2876 ----------------------------------------------------------------------------------------------------------------------------
2878 Output: sum(t1.c1), count(t2.c1)
2880 Output: t1.c1, t2.c1
2881 Filter: (((((t1.c1 * t2.c1) / (t1.c1 * t2.c1)))::double precision * random()) <= '1'::double precision)
2882 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2883 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"))))
2886 -- GROUP BY clause having expressions
2887 explain (verbose, costs off)
2888 select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
2890 ------------------------------------------------------------------------------------------------------------------
2892 Output: ((c2 / 2)), ((sum(c2) * (c2 / 2)))
2893 Relations: Aggregate on (public.ft1)
2894 Remote SQL: SELECT (c2 / 2), (sum(c2) * (c2 / 2)) FROM "S 1"."T 1" GROUP BY 1 ORDER BY (c2 / 2) ASC NULLS LAST
2897 select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
2899 ----------+----------
2907 -- Aggregates in subquery are pushed down.
2908 set enable_incremental_sort = off;
2909 explain (verbose, costs off)
2910 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;
2912 ---------------------------------------------------------------------------------------------------------------------------------------------
2914 Output: count(ft1.c2), sum(ft1.c2)
2916 Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision))
2917 Relations: Aggregate on (public.ft1)
2918 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
2921 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;
2927 reset enable_incremental_sort;
2928 -- Aggregate is still pushed down by taking unshippable expression out
2929 explain (verbose, costs off)
2930 select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2;
2932 ---------------------------------------------------------------------------------------------------
2934 Output: ((c2 * ((random() <= '1'::double precision))::integer)), ((sum(c1) * c2)), c2
2935 Sort Key: ((ft1.c2 * ((random() <= '1'::double precision))::integer)), ((sum(ft1.c1) * ft1.c2))
2937 Output: (c2 * ((random() <= '1'::double precision))::integer), ((sum(c1) * c2)), c2
2938 Relations: Aggregate on (public.ft1)
2939 Remote SQL: SELECT (sum("C 1") * c2), c2 FROM "S 1"."T 1" GROUP BY 2
2942 select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2;
2957 -- Aggregate with unshippable GROUP BY clause are not pushed
2958 explain (verbose, costs off)
2959 select c2 * (random() <= 1)::int as c2 from ft2 group by c2 * (random() <= 1)::int order by 1;
2961 ------------------------------------------------------------------------------
2963 Output: ((c2 * ((random() <= '1'::double precision))::integer))
2964 Sort Key: ((ft2.c2 * ((random() <= '1'::double precision))::integer))
2966 Output: ((c2 * ((random() <= '1'::double precision))::integer))
2967 Group Key: (ft2.c2 * ((random() <= '1'::double precision))::integer)
2968 -> Foreign Scan on public.ft2
2969 Output: (c2 * ((random() <= '1'::double precision))::integer)
2970 Remote SQL: SELECT c2 FROM "S 1"."T 1"
2973 -- GROUP BY clause in various forms, cardinal, alias and constant expression
2974 explain (verbose, costs off)
2975 select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2;
2977 ------------------------------------------------------------------------------------------------------------
2979 Output: (count(c2)), c2, 5, 7.0, 9
2980 Relations: Aggregate on (public.ft1)
2981 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
2984 select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2;
2999 -- GROUP BY clause referring to same column multiple times
3000 -- Also, ORDER BY contains an aggregate function
3001 explain (verbose, costs off)
3002 select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1);
3004 ----------------------------------------------------------------------------------------------------------------------------
3006 Output: c2, c2, (sum(c1))
3007 Relations: Aggregate on (public.ft1)
3008 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
3011 select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1);
3019 -- Testing HAVING clause shippability
3020 explain (verbose, costs off)
3021 select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
3023 ------------------------------------------------------------------------------------------------------------------------------------------------------------
3025 Output: c2, (sum(c1))
3026 Relations: Aggregate on (public.ft2)
3027 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
3030 select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
3037 -- Unshippable HAVING clause will be evaluated locally, and other qual in HAVING clause is pushed down
3038 explain (verbose, costs off)
3039 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;
3041 ---------------------------------------------------------------------------------------------------------------------------------------
3045 Output: ft1.c5, NULL::bigint, (sqrt((ft1.c2)::double precision))
3046 Filter: (((((avg(ft1.c1)) / (avg(ft1.c1))))::double precision * random()) <= '1'::double precision)
3047 Relations: Aggregate on (public.ft1)
3048 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))
3051 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;
3057 -- Aggregate in HAVING clause is not pushable, and thus aggregation is not pushed down
3058 explain (verbose, costs off)
3059 select sum(c1) from ft1 group by c2 having avg(c1 * (random() <= 1)::int) > 100 order by 1;
3061 ---------------------------------------------------------------------------------------------------
3063 Output: (sum(c1)), c2
3064 Sort Key: (sum(ft1.c1))
3068 Filter: (avg((ft1.c1 * ((random() <= '1'::double precision))::integer)) > '100'::numeric)
3069 -> Foreign Scan on public.ft1
3071 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1"
3074 -- Remote aggregate in combination with a local Param (for the output
3075 -- of an initplan) can be trouble, per bug #15781
3076 explain (verbose, costs off)
3077 select exists(select 1 from pg_enum), sum(c1) from ft1;
3079 --------------------------------------------------
3081 Output: (InitPlan 1).col1, (sum(ft1.c1))
3082 Relations: Aggregate on (public.ft1)
3083 Remote SQL: SELECT sum("C 1") FROM "S 1"."T 1"
3085 -> Seq Scan on pg_catalog.pg_enum
3088 select exists(select 1 from pg_enum), sum(c1) from ft1;
3094 explain (verbose, costs off)
3095 select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1;
3097 ---------------------------------------------------
3099 Output: (InitPlan 1).col1, sum(ft1.c1)
3101 -> Seq Scan on pg_catalog.pg_enum
3102 -> Foreign Scan on public.ft1
3104 Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
3107 select exists(select 1 from pg_enum), sum(c1) from ft1 group by 1;
3113 -- Testing ORDER BY, DISTINCT, FILTER, Ordered-sets and VARIADIC within aggregates
3114 -- ORDER BY within aggregate, same column used to order
3115 explain (verbose, costs off)
3116 select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1;
3118 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3120 Output: (array_agg(c1 ORDER BY c1)), c2
3121 Relations: Aggregate on (public.ft1)
3122 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
3125 select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1;
3127 --------------------------------
3128 {1,11,21,31,41,51,61,71,81,91}
3129 {2,12,22,32,42,52,62,72,82,92}
3130 {3,13,23,33,43,53,63,73,83,93}
3131 {4,14,24,34,44,54,64,74,84,94}
3132 {5,15,25,35,45,55,65,75,85,95}
3133 {6,16,26,36,46,56,66,76,86,96}
3134 {7,17,27,37,47,57,67,77,87,97}
3135 {8,18,28,38,48,58,68,78,88,98}
3136 {9,19,29,39,49,59,69,79,89,99}
3137 {10,20,30,40,50,60,70,80,90}
3140 -- ORDER BY within aggregate, different column used to order also using DESC
3141 explain (verbose, costs off)
3142 select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50;
3144 -------------------------------------------------------------------------------------------------------------------------
3146 Output: (array_agg(c5 ORDER BY c1 DESC))
3147 Relations: Aggregate on (public.ft2)
3148 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))
3151 select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50;
3153 ------------------------------------------------------------------------------------------------------------------------------------------
3154 {"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"}
3157 -- DISTINCT within aggregate
3158 explain (verbose, costs off)
3159 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;
3161 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3163 Output: (array_agg(DISTINCT (t1.c1 % 5))), ((t2.c1 % 3))
3164 Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
3165 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
3168 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;
3175 -- DISTINCT combined with ORDER BY within aggregate
3176 explain (verbose, costs off)
3177 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;
3179 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3181 Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))), ((t2.c1 % 3))
3182 Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
3183 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
3186 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;
3193 explain (verbose, costs off)
3194 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;
3196 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3198 Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)), ((t2.c1 % 3))
3199 Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
3200 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
3203 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;
3210 -- FILTER within aggregate
3211 explain (verbose, costs off)
3212 select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last;
3214 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3216 Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2
3217 Relations: Aggregate on (public.ft1)
3218 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
3221 select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last;
3236 -- DISTINCT, ORDER BY and FILTER within aggregate
3237 explain (verbose, costs off)
3238 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;
3240 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3242 Output: (sum((c1 % 3))), (sum(DISTINCT (c1 % 3) ORDER BY (c1 % 3)) FILTER (WHERE ((c1 % 3) < 2))), c2
3243 Relations: Aggregate on (public.ft1)
3244 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
3247 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;
3253 -- Outer query is aggregation query
3254 explain (verbose, costs off)
3255 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;
3257 ------------------------------------------------------------------------------------------------------------------------------
3259 Output: ((SubPlan 1))
3261 Output: ((SubPlan 1))
3262 Sort Key: ((SubPlan 1))
3265 Relations: Aggregate on (public.ft2 t2)
3266 Remote SQL: SELECT count(*) FILTER (WHERE ((c2 = 6) AND ("C 1" < 10))) FROM "S 1"."T 1" WHERE (((c2 % 6) = 0))
3268 -> Foreign Scan on public.ft1 t1
3269 Output: (count(*) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))))
3270 Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE (("C 1" = 6))
3273 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;
3279 -- Inner query is aggregation query
3280 explain (verbose, costs off)
3281 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;
3283 ------------------------------------------------------------------------------------------------------------------------------------------------------
3285 Output: ((SubPlan 1))
3287 Output: ((SubPlan 1))
3288 Sort Key: ((SubPlan 1))
3289 -> Foreign Scan on public.ft2 t2
3291 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (((c2 % 6) = 0))
3294 Output: (count(t1.c1) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))))
3295 Relations: Aggregate on (public.ft1 t1)
3296 Remote SQL: SELECT count("C 1") FILTER (WHERE (($1::integer = 6) AND ($2::integer < 10))) FROM "S 1"."T 1" WHERE (("C 1" = 6))
3299 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;
3306 -- Aggregate not pushed down as FILTER condition is not pushable
3307 explain (verbose, costs off)
3308 select sum(c1) filter (where (c1 / c1) * random() <= 1) from ft1 group by c2 order by 1;
3310 ------------------------------------------------------------------------------------------------------------------------
3312 Output: (sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision))), c2
3313 Sort Key: (sum(ft1.c1) FILTER (WHERE ((((ft1.c1 / ft1.c1))::double precision * random()) <= '1'::double precision)))
3315 Output: sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision)), c2
3317 -> Foreign Scan on public.ft1
3319 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1"
3322 explain (verbose, costs off)
3323 select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1;
3325 -------------------------------------------------------------------------------
3327 Output: sum(ft1.c2) FILTER (WHERE (ANY (ft1.c2 = (hashed SubPlan 1).col1)))
3328 -> Foreign Scan on public.ft1
3330 Remote SQL: SELECT c2 FROM "S 1"."T 1"
3332 -> Foreign Scan on public.ft1 ft1_1
3334 Remote SQL: SELECT c2 FROM "S 1"."T 1" WHERE ((c2 < 5))
3337 -- Ordered-sets within aggregate
3338 explain (verbose, costs off)
3339 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;
3341 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3343 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)))
3346 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)))
3347 Relations: Aggregate on (public.ft1)
3348 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))
3351 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;
3352 c2 | rank | percentile_cont
3353 ----+------+-----------------
3361 -- Using multiple arguments within aggregates
3362 explain (verbose, costs off)
3363 select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1;
3365 --------------------------------------------------------------------------------------------------------------------------------------------------------------------
3367 Output: c1, (rank(c1, c2) WITHIN GROUP (ORDER BY c1, c2)), c2
3368 Relations: Aggregate on (public.ft1)
3369 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
3372 select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1;
3378 -- User defined function for user defined aggregate, VARIADIC
3379 create function least_accum(anyelement, variadic anyarray)
3380 returns anyelement language sql as
3381 'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)';
3382 create aggregate least_agg(variadic items anyarray) (
3383 stype = anyelement, sfunc = least_accum
3385 -- Disable hash aggregation for plan stability.
3386 set enable_hashagg to false;
3387 -- Not pushed down due to user defined aggregate
3388 explain (verbose, costs off)
3389 select c2, least_agg(c1) from ft1 group by c2 order by c2;
3391 ----------------------------------------------------------------------------------
3393 Output: c2, least_agg(VARIADIC ARRAY[c1])
3395 -> Foreign Scan on public.ft1
3397 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
3400 -- Add function and aggregate into extension
3401 alter extension postgres_fdw add function least_accum(anyelement, variadic anyarray);
3402 alter extension postgres_fdw add aggregate least_agg(variadic items anyarray);
3403 alter server loopback options (set extensions 'postgres_fdw');
3404 -- Now aggregate will be pushed. Aggregate will display VARIADIC argument.
3405 explain (verbose, costs off)
3406 select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2;
3408 -----------------------------------------------------------------------------------------------------------------------
3410 Output: c2, (least_agg(VARIADIC ARRAY[c1]))
3413 Output: c2, (least_agg(VARIADIC ARRAY[c1]))
3414 Relations: Aggregate on (public.ft1)
3415 Remote SQL: SELECT c2, public.least_agg(VARIADIC ARRAY["C 1"]) FROM "S 1"."T 1" WHERE ((c2 < 100)) GROUP BY 1
3418 select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2;
3433 -- Remove function and aggregate from extension
3434 alter extension postgres_fdw drop function least_accum(anyelement, variadic anyarray);
3435 alter extension postgres_fdw drop aggregate least_agg(variadic items anyarray);
3436 alter server loopback options (set extensions 'postgres_fdw');
3437 -- Not pushed down as we have dropped objects from extension.
3438 explain (verbose, costs off)
3439 select c2, least_agg(c1) from ft1 group by c2 order by c2;
3441 ----------------------------------------------------------------------------------
3443 Output: c2, least_agg(VARIADIC ARRAY[c1])
3445 -> Foreign Scan on public.ft1
3447 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
3451 reset enable_hashagg;
3452 drop aggregate least_agg(variadic items anyarray);
3453 drop function least_accum(anyelement, variadic anyarray);
3454 -- Testing USING OPERATOR() in ORDER BY within aggregate.
3455 -- For this, we need user defined operators along with operator family and
3456 -- operator class. Create those and then add them in extension. Note that
3457 -- user defined objects are considered unshippable unless they are part of
3459 create operator public.<^ (
3464 create operator public.=^ (
3469 create operator public.>^ (
3474 create operator family my_op_family using btree;
3475 create function my_op_cmp(a int, b int) returns int as
3476 $$begin return btint4cmp(a, b); end $$ language plpgsql;
3477 create operator class my_op_class for type int using btree family my_op_family as
3478 operator 1 public.<^,
3479 operator 3 public.=^,
3480 operator 5 public.>^,
3481 function 1 my_op_cmp(int, int);
3482 -- This will not be pushed as user defined sort operator is not part of the
3484 explain (verbose, costs off)
3485 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3487 --------------------------------------------------------------------------------------------------
3489 Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2
3492 Sort Key: ft2.c1 USING <^
3493 -> Foreign Scan on public.ft2
3495 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6))
3498 -- This should not be pushed either.
3499 explain (verbose, costs off)
3500 select * from ft2 order by c1 using operator(public.<^);
3502 -------------------------------------------------------------------------------
3504 Output: c1, c2, c3, c4, c5, c6, c7, c8
3505 Sort Key: ft2.c1 USING <^
3506 -> Foreign Scan on public.ft2
3507 Output: c1, c2, c3, c4, c5, c6, c7, c8
3508 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
3511 -- Update local stats on ft2
3513 -- Add into extension
3514 alter extension postgres_fdw add operator class my_op_class using btree;
3515 alter extension postgres_fdw add function my_op_cmp(a int, b int);
3516 alter extension postgres_fdw add operator family my_op_family using btree;
3517 alter extension postgres_fdw add operator public.<^(int, int);
3518 alter extension postgres_fdw add operator public.=^(int, int);
3519 alter extension postgres_fdw add operator public.>^(int, int);
3520 alter server loopback options (set extensions 'postgres_fdw');
3521 -- Now this will be pushed as sort operator is part of the extension.
3522 alter server loopback options (add fdw_tuple_cost '0.5');
3523 explain (verbose, costs off)
3524 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3526 ----------------------------------------------------------------------------------------------------------------------------------------------------------------
3528 Output: (array_agg(c1 ORDER BY c1 USING <^ NULLS LAST)), c2
3529 Relations: Aggregate on (public.ft2)
3530 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
3533 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3535 --------------------------------
3536 {6,16,26,36,46,56,66,76,86,96}
3539 alter server loopback options (drop fdw_tuple_cost);
3540 -- This should be pushed too.
3541 explain (verbose, costs off)
3542 select * from ft2 order by c1 using operator(public.<^);
3544 -----------------------------------------------------------------------------------------------------------------------------
3545 Foreign Scan on public.ft2
3546 Output: c1, c2, c3, c4, c5, c6, c7, c8
3547 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
3550 -- Remove from extension
3551 alter extension postgres_fdw drop operator class my_op_class using btree;
3552 alter extension postgres_fdw drop function my_op_cmp(a int, b int);
3553 alter extension postgres_fdw drop operator family my_op_family using btree;
3554 alter extension postgres_fdw drop operator public.<^(int, int);
3555 alter extension postgres_fdw drop operator public.=^(int, int);
3556 alter extension postgres_fdw drop operator public.>^(int, int);
3557 alter server loopback options (set extensions 'postgres_fdw');
3558 -- This will not be pushed as sort operator is now removed from the extension.
3559 explain (verbose, costs off)
3560 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3562 --------------------------------------------------------------------------------------------------
3564 Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2
3567 Sort Key: ft2.c1 USING <^
3568 -> Foreign Scan on public.ft2
3570 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6))
3574 drop operator class my_op_class using btree;
3575 drop function my_op_cmp(a int, b int);
3576 drop operator family my_op_family using btree;
3577 drop operator public.>^(int, int);
3578 drop operator public.=^(int, int);
3579 drop operator public.<^(int, int);
3580 -- Input relation to aggregate push down hook is not safe to pushdown and thus
3581 -- the aggregate cannot be pushed down to foreign server.
3582 explain (verbose, costs off)
3583 select count(t1.c3) from ft2 t1 left join ft2 t2 on (t1.c1 = random() * t2.c2);
3585 -------------------------------------------------------------------------------------------
3587 Output: count(t1.c3)
3588 -> Nested Loop Left Join
3590 Join Filter: ((t1.c1)::double precision = (random() * (t2.c2)::double precision))
3591 -> Foreign Scan on public.ft2 t1
3592 Output: t1.c3, t1.c1
3593 Remote SQL: SELECT "C 1", c3 FROM "S 1"."T 1"
3596 -> Foreign Scan on public.ft2 t2
3598 Remote SQL: SELECT c2 FROM "S 1"."T 1"
3601 -- Subquery in FROM clause having aggregate
3602 explain (verbose, costs off)
3603 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;
3605 -----------------------------------------------------------------------------------------------
3607 Output: (count(*)), x.b
3608 Sort Key: (count(*)), x.b
3610 Output: count(*), x.b
3615 Hash Cond: (ft1.c2 = x.a)
3616 -> Foreign Scan on public.ft1
3618 Remote SQL: SELECT c2 FROM "S 1"."T 1"
3621 -> Subquery Scan on x
3624 Output: ft1_1.c2, (sum(ft1_1.c1))
3625 Relations: Aggregate on (public.ft1 ft1_1)
3626 Remote SQL: SELECT c2, sum("C 1") FROM "S 1"."T 1" GROUP BY 1
3629 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;
3644 -- FULL join with IS NULL check in HAVING
3645 explain (verbose, costs off)
3646 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;
3648 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3650 Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1
3651 Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
3652 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
3655 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;
3657 ---------------------+-----
3658 51.0000000000000000 |
3663 -- Aggregate over FULL join needing to deparse the joining relations as
3665 explain (verbose, costs off)
3666 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);
3668 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3670 Output: (count(*)), (sum(ft4.c1)), (avg(ft5.c1))
3671 Relations: Aggregate on ((public.ft4) FULL JOIN (public.ft5))
3672 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))))
3675 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);
3677 -------+-----+---------------------
3678 8 | 330 | 55.5000000000000000
3681 -- ORDER BY expression is part of the target list but not pushed down to
3683 explain (verbose, costs off)
3684 select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1;
3686 --------------------------------------------------------------------------------
3688 Output: (((sum(c2)) * ((random() <= '1'::double precision))::integer))
3689 Sort Key: (((sum(ft1.c2)) * ((random() <= '1'::double precision))::integer))
3691 Output: ((sum(c2)) * ((random() <= '1'::double precision))::integer)
3692 Relations: Aggregate on (public.ft1)
3693 Remote SQL: SELECT sum(c2) FROM "S 1"."T 1"
3696 select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1;
3702 -- LATERAL join, with parameterization
3703 set enable_hashagg to false;
3704 explain (verbose, costs off)
3705 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;
3707 ------------------------------------------------------------------------------------------------------
3709 Output: t1.c2, qry.sum
3712 Output: t1.c2, qry.sum
3713 -> Index Scan using t1_pkey on "S 1"."T 1" t1
3714 Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
3715 Index Cond: (t1."C 1" < 100)
3717 -> Subquery Scan on qry
3718 Output: qry.sum, t2.c1
3719 Filter: ((t1.c2 * 2) = qry.sum)
3721 Output: (sum((t2.c1 + t1."C 1"))), t2.c1
3722 Relations: Aggregate on (public.ft2 t2)
3723 Remote SQL: SELECT sum(("C 1" + $1::integer)), "C 1" FROM "S 1"."T 1" GROUP BY 2
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;
3733 reset enable_hashagg;
3734 -- bug #15613: bad plan for foreign table scan with lateral reference
3735 EXPLAIN (VERBOSE, COSTS OFF)
3736 SELECT ref_0.c2, subq_1.*
3738 "S 1"."T 1" AS ref_0,
3740 SELECT ref_0."C 1" c1, subq_0.*
3741 FROM (SELECT ref_0.c2, ref_1.c3
3742 FROM ft1 AS ref_1) AS subq_0
3743 RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3)
3745 WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001'
3746 ORDER BY ref_0."C 1";
3748 ---------------------------------------------------------------------------------------------------------
3750 Output: ref_0.c2, ref_0."C 1", (ref_0.c2), ref_1.c3, ref_0."C 1"
3752 Output: ref_0.c2, ref_0."C 1", ref_1.c3, (ref_0.c2)
3753 -> Index Scan using t1_pkey on "S 1"."T 1" ref_0
3754 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
3755 Index Cond: (ref_0."C 1" < 10)
3756 -> Foreign Scan on public.ft1 ref_1
3757 Output: ref_1.c3, ref_0.c2
3758 Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE ((c3 = '00001'))
3761 -> Foreign Scan on public.ft2 ref_3
3763 Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE ((c3 = '00001'))
3766 SELECT ref_0.c2, subq_1.*
3768 "S 1"."T 1" AS ref_0,
3770 SELECT ref_0."C 1" c1, subq_0.*
3771 FROM (SELECT ref_0.c2, ref_1.c3
3772 FROM ft1 AS ref_1) AS subq_0
3773 RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3)
3775 WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001'
3776 ORDER BY ref_0."C 1";
3778 ----+----+----+-------
3790 -- Check with placeHolderVars
3791 explain (verbose, costs off)
3792 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);
3794 ----------------------------------------------------------------------------------------------------------------------------------------------------------
3796 Output: sum(q.a), count(q.b)
3797 -> Nested Loop Left Join
3800 Join Filter: ((ft4.c1)::numeric <= q.b)
3801 -> Foreign Scan on public.ft4
3802 Output: ft4.c1, ft4.c2, ft4.c3
3803 Remote SQL: SELECT c1 FROM "S 1"."T 3"
3806 -> Subquery Scan on q
3809 Output: 13, (avg(ft1.c1)), NULL::bigint
3810 Relations: Aggregate on ((public.ft2) LEFT JOIN (public.ft1))
3811 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"))))
3814 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);
3820 -- Not supported cases
3822 explain (verbose, costs off)
3823 select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last;
3825 ------------------------------------------------------------------------------
3827 Output: c2, (sum(c1))
3833 -> Foreign Scan on public.ft1
3835 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3))
3838 select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last;
3847 explain (verbose, costs off)
3848 select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last;
3850 ------------------------------------------------------------------------------
3852 Output: c2, (sum(c1))
3858 -> Foreign Scan on public.ft1
3860 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3))
3863 select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last;
3872 explain (verbose, costs off)
3873 select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last;
3875 ----------------------------------------------------------------------------------
3877 Output: c2, c6, (sum(c1))
3878 Sort Key: ft1.c2, ft1.c6
3880 Output: c2, c6, sum(c1)
3883 -> Foreign Scan on public.ft1
3885 Remote SQL: SELECT "C 1", c2, c6 FROM "S 1"."T 1" WHERE ((c2 < 3))
3888 select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last;
3899 explain (verbose, costs off)
3900 select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last;
3902 ------------------------------------------------------------------------------
3904 Output: c2, (sum(c1)), (GROUPING(c2))
3907 Output: c2, sum(c1), GROUPING(c2)
3909 -> Foreign Scan on public.ft1
3911 Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3))
3914 select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last;
3916 ----+-------+----------
3922 -- DISTINCT itself is not pushed down, whereas underneath aggregate is pushed
3923 explain (verbose, costs off)
3924 select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1;
3926 -------------------------------------------------------------------------------------------------------
3928 Output: ((sum(c1) / 1000)), c2
3930 Output: ((sum(c1) / 1000)), c2
3931 Sort Key: ((sum(ft2.c1) / 1000))
3933 Output: ((sum(c1) / 1000)), c2
3934 Relations: Aggregate on (public.ft2)
3935 Remote SQL: SELECT (sum("C 1") / 1000), c2 FROM "S 1"."T 1" WHERE ((c2 < 6)) GROUP BY 2
3938 select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1;
3946 explain (verbose, costs off)
3947 select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1;
3949 ------------------------------------------------------------------------------------------------------------
3951 Output: c2, (sum(c2)), (count(c2) OVER (?)), ((c2 % 2))
3954 Output: c2, (sum(c2)), count(c2) OVER (?), ((c2 % 2))
3956 Output: c2, ((c2 % 2)), (sum(c2))
3957 Sort Key: ((ft2.c2 % 2))
3959 Output: c2, ((c2 % 2)), (sum(c2))
3960 Relations: Aggregate on (public.ft2)
3961 Remote SQL: SELECT c2, (c2 % 2), sum(c2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1
3964 select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1;
3979 explain (verbose, costs off)
3980 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;
3982 ---------------------------------------------------------------------------------------------------
3984 Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2))
3987 Output: c2, array_agg(c2) OVER (?), ((c2 % 2))
3989 Output: c2, ((c2 % 2))
3990 Sort Key: ((ft1.c2 % 2)), ft1.c2 DESC
3992 Output: c2, ((c2 % 2))
3993 Relations: Aggregate on (public.ft1)
3994 Remote SQL: SELECT c2, (c2 % 2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1
3997 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;
4012 explain (verbose, costs off)
4013 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;
4015 ---------------------------------------------------------------------------------------------------
4017 Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2))
4020 Output: c2, array_agg(c2) OVER (?), ((c2 % 2))
4022 Output: c2, ((c2 % 2))
4023 Sort Key: ((ft1.c2 % 2)), ft1.c2
4025 Output: c2, ((c2 % 2))
4026 Relations: Aggregate on (public.ft1)
4027 Remote SQL: SELECT c2, (c2 % 2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1
4030 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;
4045 -- ===================================================================
4046 -- parameterized queries
4047 -- ===================================================================
4049 PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $1 AND t2.c1 = $2;
4050 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2);
4052 ------------------------------------------------------------------------------------------------------------------------------
4054 Output: t1.c3, t2.c3
4055 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
4056 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))))
4065 EXECUTE st1(101, 101);
4071 SET enable_hashjoin TO off;
4072 SET enable_sort TO off;
4073 -- subquery using stable function (can't be sent to remote)
4074 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;
4075 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st2(10, 20);
4077 ----------------------------------------------------------------------------------------------------------------------------------
4078 Nested Loop Semi Join
4079 Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
4080 Join Filter: (t2.c3 = t1.c3)
4081 -> Foreign Scan on public.ft1 t1
4082 Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
4083 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
4086 -> Foreign Scan on public.ft2 t2
4088 Filter: (date(t2.c4) = '01-17-1970'::date)
4089 Remote SQL: SELECT c3, c4 FROM "S 1"."T 1" WHERE (("C 1" > 10))
4092 EXECUTE st2(10, 20);
4093 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4094 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4095 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo
4098 EXECUTE st2(101, 121);
4099 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4100 -----+----+-------+------------------------------+--------------------------+----+------------+-----
4101 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo
4104 RESET enable_hashjoin;
4106 -- subquery using immutable function (can be sent to remote)
4107 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;
4108 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st3(10, 20);
4110 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4112 Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
4113 Relations: (public.ft1 t1) SEMI JOIN (public.ft2 t2)
4114 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))) ORDER BY r1."C 1" ASC NULLS LAST
4117 EXECUTE st3(10, 20);
4118 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4119 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4120 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo
4123 EXECUTE st3(20, 30);
4124 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4125 ----+----+----+----+----+----+----+----
4128 -- custom plan should be chosen initially
4129 PREPARE st4(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 = $1;
4130 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
4132 ---------------------------------------------------------------------------------------------
4133 Foreign Scan on public.ft1 t1
4134 Output: c1, c2, c3, c4, c5, c6, c7, c8
4135 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4138 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
4140 ---------------------------------------------------------------------------------------------
4141 Foreign Scan on public.ft1 t1
4142 Output: c1, c2, c3, c4, c5, c6, c7, c8
4143 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4146 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
4148 ---------------------------------------------------------------------------------------------
4149 Foreign Scan on public.ft1 t1
4150 Output: c1, c2, c3, c4, c5, c6, c7, c8
4151 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 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 -- once we try it enough times, should switch to generic plan
4171 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
4173 -------------------------------------------------------------------------------------------------------
4174 Foreign Scan on public.ft1 t1
4175 Output: c1, c2, c3, c4, c5, c6, c7, c8
4176 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
4179 -- value of $1 should not be sent to remote
4180 PREPARE st5(user_enum,int) AS SELECT * FROM ft1 t1 WHERE c8 = $1 and c1 = $2;
4181 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4183 ---------------------------------------------------------------------------------------------
4184 Foreign Scan on public.ft1 t1
4185 Output: c1, c2, c3, c4, c5, c6, c7, c8
4186 Filter: (t1.c8 = 'foo'::user_enum)
4187 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4190 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4192 ---------------------------------------------------------------------------------------------
4193 Foreign Scan on public.ft1 t1
4194 Output: c1, c2, c3, c4, c5, c6, c7, c8
4195 Filter: (t1.c8 = 'foo'::user_enum)
4196 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4199 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4201 ---------------------------------------------------------------------------------------------
4202 Foreign Scan on public.ft1 t1
4203 Output: c1, c2, c3, c4, c5, c6, c7, c8
4204 Filter: (t1.c8 = 'foo'::user_enum)
4205 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4208 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4210 ---------------------------------------------------------------------------------------------
4211 Foreign Scan on public.ft1 t1
4212 Output: c1, c2, c3, c4, c5, c6, c7, c8
4213 Filter: (t1.c8 = 'foo'::user_enum)
4214 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4217 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4219 ---------------------------------------------------------------------------------------------
4220 Foreign Scan on public.ft1 t1
4221 Output: c1, c2, c3, c4, c5, c6, c7, c8
4222 Filter: (t1.c8 = 'foo'::user_enum)
4223 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
4226 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
4228 -------------------------------------------------------------------------------------------------------
4229 Foreign Scan on public.ft1 t1
4230 Output: c1, c2, c3, c4, c5, c6, c7, c8
4231 Filter: (t1.c8 = $1)
4232 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
4235 EXECUTE st5('foo', 1);
4236 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4237 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4238 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4241 -- altering FDW options requires replanning
4242 PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2;
4243 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
4245 ----------------------------------------------------------------------------------------------
4246 Foreign Scan on public.ft1 t1
4247 Output: c1, c2, c3, c4, c5, c6, c7, c8
4248 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = c2))
4251 PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo');
4252 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
4254 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4255 Insert on public.ft1
4256 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)
4259 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
4262 ALTER TABLE "S 1"."T 1" RENAME TO "T 0";
4263 ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 0');
4264 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
4266 ----------------------------------------------------------------------------------------------
4267 Foreign Scan on public.ft1 t1
4268 Output: c1, c2, c3, c4, c5, c6, c7, c8
4269 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 0" WHERE (("C 1" = c2))
4273 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4274 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4275 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4276 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
4277 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
4278 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo
4279 5 | 5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo
4280 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo
4281 7 | 7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
4282 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
4283 9 | 9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo
4286 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
4288 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4289 Insert on public.ft1
4290 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)
4293 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
4296 ALTER TABLE "S 1"."T 0" RENAME TO "T 1";
4297 ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 1');
4298 PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
4299 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
4301 -----------------------------------------------------------------------------------------
4304 Relations: Aggregate on (public.ft1 t1)
4305 Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2))
4308 ALTER SERVER loopback OPTIONS (DROP extensions);
4309 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
4311 -----------------------------------------------------------
4314 -> Foreign Scan on public.ft1 t1
4316 Filter: (t1.c1 === t1.c2)
4317 Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
4326 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
4336 -- System columns, except ctid and oid, should not be sent to remote
4337 EXPLAIN (VERBOSE, COSTS OFF)
4338 SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
4340 -------------------------------------------------------------------------------
4342 Output: c1, c2, c3, c4, c5, c6, c7, c8
4343 -> Foreign Scan on public.ft1 t1
4344 Output: c1, c2, c3, c4, c5, c6, c7, c8
4345 Filter: (t1.tableoid = '1259'::oid)
4346 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
4349 SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1;
4350 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4351 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4352 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4355 EXPLAIN (VERBOSE, COSTS OFF)
4356 SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1;
4358 -----------------------------------------------------------------------------------------
4359 Foreign Scan on public.ft1 t1
4360 Output: (tableoid)::regclass, c1, c2, c3, c4, c5, c6, c7, c8
4361 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" LIMIT 1::bigint
4364 SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1;
4365 tableoid | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4366 ----------+----+----+-------+------------------------------+--------------------------+----+------------+-----
4367 ft1 | 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4370 EXPLAIN (VERBOSE, COSTS OFF)
4371 SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)';
4373 --------------------------------------------------------------------------------------------------
4374 Foreign Scan on public.ft1 t1
4375 Output: c1, c2, c3, c4, c5, c6, c7, c8
4376 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((ctid = '(0,2)'))
4379 SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)';
4380 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4381 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4382 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
4385 EXPLAIN (VERBOSE, COSTS OFF)
4386 SELECT ctid, * FROM ft1 t1 LIMIT 1;
4388 -----------------------------------------------------------------------------------------------
4389 Foreign Scan on public.ft1 t1
4390 Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8
4391 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" LIMIT 1::bigint
4394 SELECT ctid, * FROM ft1 t1 LIMIT 1;
4395 ctid | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4396 -------+----+----+-------+------------------------------+--------------------------+----+------------+-----
4397 (0,1) | 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4400 -- ===================================================================
4401 -- used in PL/pgSQL function
4402 -- ===================================================================
4403 CREATE OR REPLACE FUNCTION f_test(p_c1 int) RETURNS int AS $$
4407 SELECT c1 INTO v_c1 FROM ft1 WHERE c1 = p_c1 LIMIT 1;
4408 PERFORM c1 FROM ft1 WHERE c1 = p_c1 AND p_c1 = v_c1 LIMIT 1;
4411 $$ LANGUAGE plpgsql;
4418 DROP FUNCTION f_test(int);
4419 -- ===================================================================
4421 -- ===================================================================
4422 -- remote table is not created here
4423 CREATE FOREIGN TABLE reindex_foreign (c1 int, c2 int)
4424 SERVER loopback2 OPTIONS (table_name 'reindex_local');
4425 REINDEX TABLE reindex_foreign; -- error
4426 ERROR: "reindex_foreign" is not a table or materialized view
4427 REINDEX TABLE CONCURRENTLY reindex_foreign; -- error
4428 ERROR: "reindex_foreign" is not a table or materialized view
4429 DROP FOREIGN TABLE reindex_foreign;
4430 -- partitions and foreign tables
4431 CREATE TABLE reind_fdw_parent (c1 int) PARTITION BY RANGE (c1);
4432 CREATE TABLE reind_fdw_0_10 PARTITION OF reind_fdw_parent
4433 FOR VALUES FROM (0) TO (10);
4434 CREATE FOREIGN TABLE reind_fdw_10_20 PARTITION OF reind_fdw_parent
4435 FOR VALUES FROM (10) TO (20)
4436 SERVER loopback OPTIONS (table_name 'reind_local_10_20');
4437 REINDEX TABLE reind_fdw_parent; -- ok
4438 REINDEX TABLE CONCURRENTLY reind_fdw_parent; -- ok
4439 DROP TABLE reind_fdw_parent;
4440 -- ===================================================================
4442 -- ===================================================================
4443 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int;
4444 SELECT * FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8) WHERE x1 = 1; -- ERROR
4445 ERROR: invalid input syntax for type integer: "foo"
4446 CONTEXT: column "x8" of foreign table "ftx"
4447 SELECT ftx.x1, ft2.c2, ftx.x8 FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8), ft2
4448 WHERE ftx.x1 = ft2.c1 AND ftx.x1 = 1; -- ERROR
4449 ERROR: invalid input syntax for type integer: "foo"
4450 CONTEXT: column "x8" of foreign table "ftx"
4451 SELECT ftx.x1, ft2.c2, ftx FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8), ft2
4452 WHERE ftx.x1 = ft2.c1 AND ftx.x1 = 1; -- ERROR
4453 ERROR: invalid input syntax for type integer: "foo"
4454 CONTEXT: whole-row reference to foreign table "ftx"
4455 SELECT sum(c2), array_agg(c8) FROM ft1 GROUP BY c8; -- ERROR
4456 ERROR: invalid input syntax for type integer: "foo"
4457 CONTEXT: processing expression at position 2 in select list
4458 ANALYZE ft1; -- ERROR
4459 ERROR: invalid input syntax for type integer: "foo"
4460 CONTEXT: column "c8" of foreign table "ft1"
4461 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum;
4462 -- ===================================================================
4463 -- local type can be different from remote type in some cases,
4464 -- in particular if similarly-named operators do equivalent things
4465 -- ===================================================================
4466 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE text;
4467 EXPLAIN (VERBOSE, COSTS OFF)
4468 SELECT * FROM ft1 WHERE c8 = 'foo' LIMIT 1;
4470 --------------------------------------------------------------------------------------------------------------
4471 Foreign Scan on public.ft1
4472 Output: c1, c2, c3, c4, c5, c6, c7, c8
4473 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c8 = 'foo')) LIMIT 1::bigint
4476 SELECT * FROM ft1 WHERE c8 = 'foo' LIMIT 1;
4477 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4478 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4479 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4482 EXPLAIN (VERBOSE, COSTS OFF)
4483 SELECT * FROM ft1 WHERE 'foo' = c8 LIMIT 1;
4485 --------------------------------------------------------------------------------------------------------------
4486 Foreign Scan on public.ft1
4487 Output: c1, c2, c3, c4, c5, c6, c7, c8
4488 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (('foo' = c8)) LIMIT 1::bigint
4491 SELECT * FROM ft1 WHERE 'foo' = c8 LIMIT 1;
4492 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4493 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4494 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4497 -- we declared c8 to be text locally, but it's still the same type on
4498 -- the remote which will balk if we try to do anything incompatible
4499 -- with that remote type
4500 SELECT * FROM ft1 WHERE c8 LIKE 'foo' LIMIT 1; -- ERROR
4501 ERROR: operator does not exist: public.user_enum ~~ unknown
4502 HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
4503 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
4504 SELECT * FROM ft1 WHERE c8::text LIKE 'foo' LIMIT 1; -- ERROR; cast not pushed down
4505 ERROR: operator does not exist: public.user_enum ~~ unknown
4506 HINT: No operator matches the given name and argument types. You might need to add explicit type casts.
4507 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
4508 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum;
4509 -- ===================================================================
4511 -- + local/remote error doesn't break cursor
4512 -- ===================================================================
4514 DECLARE c CURSOR FOR SELECT * FROM ft1 ORDER BY c1;
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
4523 ERROR: syntax error at or near "ERROR"
4528 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4529 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4530 2 | 2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo
4534 SELECT * FROM ft1 WHERE 1 / (c1 - 1) > 0; -- ERROR
4535 ERROR: division by zero
4536 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))
4539 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4540 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4541 3 | 3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
4544 SELECT * FROM ft1 ORDER BY c1 LIMIT 1;
4545 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4546 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4547 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo
4551 -- ===================================================================
4552 -- test handling of collations
4553 -- ===================================================================
4554 create table loct3 (f1 text collate "C" unique, f2 text, f3 varchar(10) unique);
4555 create foreign table ft3 (f1 text collate "C", f2 text, f3 varchar(10))
4556 server loopback options (table_name 'loct3', use_remote_estimate 'true');
4557 -- can be sent to remote
4558 explain (verbose, costs off) select * from ft3 where f1 = 'foo';
4560 ------------------------------------------------------------------------
4561 Foreign Scan on public.ft3
4563 Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f1 = 'foo'))
4566 explain (verbose, costs off) select * from ft3 where f1 COLLATE "C" = 'foo';
4568 ------------------------------------------------------------------------
4569 Foreign Scan on public.ft3
4571 Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f1 = 'foo'))
4574 explain (verbose, costs off) select * from ft3 where f2 = 'foo';
4576 ------------------------------------------------------------------------
4577 Foreign Scan on public.ft3
4579 Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f2 = 'foo'))
4582 explain (verbose, costs off) select * from ft3 where f3 = 'foo';
4584 ------------------------------------------------------------------------
4585 Foreign Scan on public.ft3
4587 Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f3 = 'foo'))
4590 explain (verbose, costs off) select * from ft3 f, loct3 l
4591 where f.f3 = l.f3 and l.f1 = 'foo';
4593 --------------------------------------------------------------------------------------------------
4595 Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
4596 -> Index Scan using loct3_f1_key on public.loct3 l
4597 Output: l.f1, l.f2, l.f3
4598 Index Cond: (l.f1 = 'foo'::text)
4599 -> Foreign Scan on public.ft3 f
4600 Output: f.f1, f.f2, f.f3
4601 Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f3 = $1::character varying(10)))
4604 -- can't be sent to remote
4605 explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo';
4607 ---------------------------------------------------
4608 Foreign Scan on public.ft3
4610 Filter: ((ft3.f1)::text = 'foo'::text)
4611 Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4614 explain (verbose, costs off) select * from ft3 where f1 = 'foo' COLLATE "C";
4616 ---------------------------------------------------
4617 Foreign Scan on public.ft3
4619 Filter: (ft3.f1 = 'foo'::text COLLATE "C")
4620 Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4623 explain (verbose, costs off) select * from ft3 where f2 COLLATE "C" = 'foo';
4625 ---------------------------------------------------
4626 Foreign Scan on public.ft3
4628 Filter: ((ft3.f2)::text = 'foo'::text)
4629 Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4632 explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C";
4634 ---------------------------------------------------
4635 Foreign Scan on public.ft3
4637 Filter: (ft3.f2 = 'foo'::text COLLATE "C")
4638 Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4641 explain (verbose, costs off) select * from ft3 f, loct3 l
4642 where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo';
4644 -------------------------------------------------------------
4646 Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
4648 Hash Cond: ((f.f3)::text = (l.f3)::text)
4649 -> Foreign Scan on public.ft3 f
4650 Output: f.f1, f.f2, f.f3
4651 Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4653 Output: l.f1, l.f2, l.f3
4654 -> Index Scan using loct3_f1_key on public.loct3 l
4655 Output: l.f1, l.f2, l.f3
4656 Index Cond: (l.f1 = 'foo'::text)
4659 -- ===================================================================
4660 -- test SEMI-JOIN pushdown
4661 -- ===================================================================
4662 EXPLAIN (verbose, costs off)
4663 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN ft4 ON ft2.c2 = ft4.c1
4665 AND EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)
4668 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4670 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3
4671 Relations: ((public.ft2) INNER JOIN (public.ft4)) SEMI JOIN (public.ft5)
4672 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
4675 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN ft4 ON ft2.c2 = ft4.c1
4677 AND EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)
4679 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3
4680 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------
4681 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4682 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4683 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4684 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4685 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4686 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4687 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4688 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4689 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4690 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4693 -- The same query, different join order
4694 EXPLAIN (verbose, costs off)
4695 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4696 (SELECT * FROM ft4 WHERE
4697 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4702 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4704 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3
4705 Relations: ((public.ft2) INNER JOIN (public.ft4)) SEMI JOIN (public.ft5)
4706 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
4709 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4710 (SELECT * FROM ft4 WHERE
4711 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4715 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3
4716 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------
4717 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4718 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4719 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4720 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4721 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4722 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4723 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4724 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4725 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4726 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4730 EXPLAIN (verbose, costs off)
4731 SELECT ft2.*, ft4.* FROM ft2 LEFT JOIN
4732 (SELECT * FROM ft4 WHERE
4733 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4736 ORDER BY ft2.c1 LIMIT 10;
4738 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4740 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3
4741 Relations: (public.ft2) LEFT JOIN ((public.ft4) SEMI JOIN (public.ft5))
4742 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
4745 SELECT ft2.*, ft4.* FROM ft2 LEFT JOIN
4746 (SELECT * FROM ft4 WHERE
4747 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4750 ORDER BY ft2.c1 LIMIT 10;
4751 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3
4752 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------
4753 901 | 1 | 00901 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1 | 1 | foo | | |
4754 902 | 2 | 00902 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2 | 2 | foo | | |
4755 903 | 3 | 00903 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo | | |
4756 904 | 4 | 00904 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4 | 4 | foo | | |
4757 905 | 5 | 00905 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo | | |
4758 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4759 907 | 7 | 00907 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo | | |
4760 908 | 8 | 00908 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo | | |
4761 909 | 9 | 00909 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo | | |
4762 910 | 0 | 00910 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo | | |
4765 -- Several semi-joins per upper level join
4766 EXPLAIN (verbose, costs off)
4767 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4768 (SELECT * FROM ft4 WHERE
4769 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4771 INNER JOIN (SELECT * FROM ft5 WHERE
4772 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft5.c1)) ft5
4775 ORDER BY ft2.c1 LIMIT 10;
4777 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4779 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3
4780 Relations: ((((public.ft2) INNER JOIN (public.ft4)) SEMI JOIN (public.ft5)) INNER JOIN (public.ft5 ft5_1)) SEMI JOIN (public.ft4 ft4_1)
4781 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
4784 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4785 (SELECT * FROM ft4 WHERE
4786 EXISTS (SELECT 1 FROM ft5 WHERE ft4.c1 = ft5.c1)) ft4
4788 INNER JOIN (SELECT * FROM ft5 WHERE
4789 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c1 = ft5.c1)) ft5
4792 ORDER BY ft2.c1 LIMIT 10;
4793 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3
4794 -----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------
4795 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4796 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4797 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4798 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4799 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4800 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4801 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4802 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4803 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4804 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6 | 6 | foo | 6 | 7 | AAA006
4807 -- Semi-join below Semi-join
4808 EXPLAIN (verbose, costs off)
4809 SELECT ft2.* FROM ft2 WHERE
4811 SELECT c1 FROM ft2 WHERE
4812 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2))
4814 ORDER BY ft2.c1 LIMIT 10;
4816 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4818 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8
4819 Relations: (public.ft2) SEMI JOIN ((public.ft2 ft2_1) SEMI JOIN (public.ft4))
4820 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
4823 SELECT ft2.* FROM ft2 WHERE
4825 SELECT c1 FROM ft2 WHERE
4826 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2))
4828 ORDER BY ft2.c1 LIMIT 10;
4829 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4830 -----+----+-------+------------------------------+--------------------------+----+------------+-----
4831 903 | 3 | 00903 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
4832 905 | 5 | 00905 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo
4833 907 | 7 | 00907 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
4834 909 | 9 | 00909 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo
4835 913 | 3 | 00913 | Wed Jan 14 00:00:00 1970 PST | Wed Jan 14 00:00:00 1970 | 3 | 3 | foo
4836 915 | 5 | 00915 | Fri Jan 16 00:00:00 1970 PST | Fri Jan 16 00:00:00 1970 | 5 | 5 | foo
4837 917 | 7 | 00917 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
4838 919 | 9 | 00919 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | 9 | foo
4839 923 | 3 | 00923 | Sat Jan 24 00:00:00 1970 PST | Sat Jan 24 00:00:00 1970 | 3 | 3 | foo
4840 925 | 5 | 00925 | Mon Jan 26 00:00:00 1970 PST | Mon Jan 26 00:00:00 1970 | 5 | 5 | foo
4843 -- Upper level relations shouldn't refer EXISTS() subqueries
4844 EXPLAIN (verbose, costs off)
4845 SELECT * FROM ft2 ftupper WHERE
4847 SELECT c1 FROM ft2 WHERE
4848 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2) AND c1 = ftupper.c1 )
4849 AND ftupper.c1 > 900
4850 ORDER BY ftupper.c1 LIMIT 10;
4852 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4854 Output: ftupper.c1, ftupper.c2, ftupper.c3, ftupper.c4, ftupper.c5, ftupper.c6, ftupper.c7, ftupper.c8
4855 Relations: (public.ft2 ftupper) SEMI JOIN ((public.ft2) SEMI JOIN (public.ft4))
4856 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
4859 SELECT * FROM ft2 ftupper WHERE
4861 SELECT c1 FROM ft2 WHERE
4862 EXISTS (SELECT 1 FROM ft4 WHERE ft4.c2 = ft2.c2) AND c1 = ftupper.c1 )
4863 AND ftupper.c1 > 900
4864 ORDER BY ftupper.c1 LIMIT 10;
4865 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4866 -----+----+-------+------------------------------+--------------------------+----+------------+-----
4867 903 | 3 | 00903 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3 | 3 | foo
4868 905 | 5 | 00905 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5 | 5 | foo
4869 907 | 7 | 00907 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
4870 909 | 9 | 00909 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | 9 | foo
4871 913 | 3 | 00913 | Wed Jan 14 00:00:00 1970 PST | Wed Jan 14 00:00:00 1970 | 3 | 3 | foo
4872 915 | 5 | 00915 | Fri Jan 16 00:00:00 1970 PST | Fri Jan 16 00:00:00 1970 | 5 | 5 | foo
4873 917 | 7 | 00917 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
4874 919 | 9 | 00919 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | 9 | foo
4875 923 | 3 | 00923 | Sat Jan 24 00:00:00 1970 PST | Sat Jan 24 00:00:00 1970 | 3 | 3 | foo
4876 925 | 5 | 00925 | Mon Jan 26 00:00:00 1970 PST | Mon Jan 26 00:00:00 1970 | 5 | 5 | foo
4879 -- EXISTS should be propagated to the highest upper inner join
4880 EXPLAIN (verbose, costs off)
4881 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4882 (SELECT * FROM ft4 WHERE EXISTS (
4883 SELECT 1 FROM ft2 WHERE ft2.c2 = ft4.c2)) ft4
4886 (SELECT * FROM ft2 WHERE EXISTS (
4887 SELECT 1 FROM ft4 WHERE ft2.c2 = ft4.c2)) ft21
4890 ORDER BY ft2.c1 LIMIT 10;
4892 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4894 Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3
4895 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)
4896 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
4899 SELECT ft2.*, ft4.* FROM ft2 INNER JOIN
4900 (SELECT * FROM ft4 WHERE EXISTS (
4901 SELECT 1 FROM ft2 WHERE ft2.c2 = ft4.c2)) ft4
4904 (SELECT * FROM ft2 WHERE EXISTS (
4905 SELECT 1 FROM ft4 WHERE ft2.c2 = ft4.c2)) ft21
4908 ORDER BY ft2.c1 LIMIT 10;
4909 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3
4910 ----+----+----+----+----+----+----+----+----+----+----
4913 -- Can't push down semi-join with inner rel vars in targetlist
4914 EXPLAIN (verbose, costs off)
4915 SELECT ft1.c1 FROM ft1 JOIN ft2 on ft1.c1 = ft2.c1 WHERE
4917 SELECT ft2.c1 FROM ft2 JOIN ft4 ON ft2.c1 = ft4.c1)
4918 ORDER BY ft1.c1 LIMIT 5;
4920 -------------------------------------------------------------------------------------------------------------------------------------------------------------------
4925 Merge Cond: (ft1.c1 = ft2_1.c1)
4927 Output: ft1.c1, ft2.c1
4928 Relations: (public.ft1) INNER JOIN (public.ft2)
4929 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
4931 Output: ft2_1.c1, ft4.c1
4932 Relations: (public.ft2 ft2_1) INNER JOIN (public.ft4)
4933 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
4936 -- ===================================================================
4937 -- test writable foreign table stuff
4938 -- ===================================================================
4939 EXPLAIN (verbose, costs off)
4940 INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
4942 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4943 Insert on public.ft2
4944 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)
4946 -> Subquery Scan on "*SELECT*"
4947 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
4948 -> Foreign Scan on public.ft2 ft2_1
4949 Output: (ft2_1.c1 + 1000), (ft2_1.c2 + 100), (ft2_1.c3 || ft2_1.c3)
4950 Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1" LIMIT 20::bigint
4953 INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
4954 INSERT INTO ft2 (c1,c2,c3)
4955 VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING *;
4956 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4957 ------+-----+-----+----+----+----+------------+----
4958 1101 | 201 | aaa | | | | ft2 |
4959 1102 | 202 | bbb | | | | ft2 |
4960 1103 | 203 | ccc | | | | ft2 |
4963 INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee');
4964 EXPLAIN (verbose, costs off)
4965 UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3; -- can be pushed down
4967 ----------------------------------------------------------------------------------------------------------------
4968 Update on public.ft2
4969 -> Foreign Update on public.ft2
4970 Remote SQL: UPDATE "S 1"."T 1" SET c2 = (c2 + 300), c3 = (c3 || '_update3') WHERE ((("C 1" % 10) = 3))
4973 UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3;
4974 EXPLAIN (verbose, costs off)
4975 UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *; -- can be pushed down
4977 ------------------------------------------------------------------------------------------------------------------------------------------------------------
4978 Update on public.ft2
4979 Output: c1, c2, c3, c4, c5, c6, c7, c8
4980 -> Foreign Update on public.ft2
4981 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
4984 UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *;
4985 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
4986 ------+-----+--------------------+------------------------------+--------------------------+----+------------+-----
4987 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
4988 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
4989 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
4990 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
4991 47 | 407 | 00047_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
4992 57 | 407 | 00057_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
4993 67 | 407 | 00067_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
4994 77 | 407 | 00077_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
4995 87 | 407 | 00087_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
4996 97 | 407 | 00097_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
4997 107 | 407 | 00107_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
4998 117 | 407 | 00117_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
4999 127 | 407 | 00127_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5000 137 | 407 | 00137_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5001 147 | 407 | 00147_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5002 157 | 407 | 00157_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5003 167 | 407 | 00167_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5004 177 | 407 | 00177_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5005 187 | 407 | 00187_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5006 197 | 407 | 00197_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5007 207 | 407 | 00207_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5008 217 | 407 | 00217_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5009 227 | 407 | 00227_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5010 237 | 407 | 00237_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5011 247 | 407 | 00247_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5012 257 | 407 | 00257_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5013 267 | 407 | 00267_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5014 277 | 407 | 00277_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5015 287 | 407 | 00287_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5016 297 | 407 | 00297_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5017 307 | 407 | 00307_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5018 317 | 407 | 00317_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5019 327 | 407 | 00327_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5020 337 | 407 | 00337_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5021 347 | 407 | 00347_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5022 357 | 407 | 00357_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5023 367 | 407 | 00367_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5024 377 | 407 | 00377_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5025 387 | 407 | 00387_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5026 397 | 407 | 00397_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5027 407 | 407 | 00407_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5028 417 | 407 | 00417_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5029 427 | 407 | 00427_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5030 437 | 407 | 00437_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5031 447 | 407 | 00447_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5032 457 | 407 | 00457_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5033 467 | 407 | 00467_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5034 477 | 407 | 00477_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5035 487 | 407 | 00487_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5036 497 | 407 | 00497_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5037 507 | 407 | 00507_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5038 517 | 407 | 00517_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5039 527 | 407 | 00527_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5040 537 | 407 | 00537_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5041 547 | 407 | 00547_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5042 557 | 407 | 00557_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5043 567 | 407 | 00567_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5044 577 | 407 | 00577_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5045 587 | 407 | 00587_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5046 597 | 407 | 00597_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5047 607 | 407 | 00607_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5048 617 | 407 | 00617_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5049 627 | 407 | 00627_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5050 637 | 407 | 00637_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5051 647 | 407 | 00647_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5052 657 | 407 | 00657_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5053 667 | 407 | 00667_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5054 677 | 407 | 00677_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5055 687 | 407 | 00687_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5056 697 | 407 | 00697_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5057 707 | 407 | 00707_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5058 717 | 407 | 00717_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5059 727 | 407 | 00727_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5060 737 | 407 | 00737_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5061 747 | 407 | 00747_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5062 757 | 407 | 00757_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5063 767 | 407 | 00767_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5064 777 | 407 | 00777_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5065 787 | 407 | 00787_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5066 797 | 407 | 00797_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5067 807 | 407 | 00807_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5068 817 | 407 | 00817_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5069 827 | 407 | 00827_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5070 837 | 407 | 00837_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5071 847 | 407 | 00847_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5072 857 | 407 | 00857_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5073 867 | 407 | 00867_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5074 877 | 407 | 00877_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5075 887 | 407 | 00887_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5076 897 | 407 | 00897_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5077 907 | 407 | 00907_update7 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7 | 7 | foo
5078 917 | 407 | 00917_update7 | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7 | 7 | foo
5079 927 | 407 | 00927_update7 | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7 | 7 | foo
5080 937 | 407 | 00937_update7 | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7 | 7 | foo
5081 947 | 407 | 00947_update7 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7 | 7 | foo
5082 957 | 407 | 00957_update7 | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7 | 7 | foo
5083 967 | 407 | 00967_update7 | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7 | 7 | foo
5084 977 | 407 | 00977_update7 | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7 | 7 | foo
5085 987 | 407 | 00987_update7 | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7 | 7 | foo
5086 997 | 407 | 00997_update7 | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7 | 7 | foo
5087 1007 | 507 | 0000700007_update7 | | | | ft2 |
5088 1017 | 507 | 0001700017_update7 | | | | ft2 |
5091 EXPLAIN (verbose, costs off)
5092 UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
5093 FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9; -- can be pushed down
5095 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5096 Update on public.ft2
5098 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))
5101 UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
5102 FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9;
5103 EXPLAIN (verbose, costs off)
5104 DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4; -- can be pushed down
5106 --------------------------------------------------------------------------------------------
5107 Delete on public.ft2
5109 -> Foreign Delete on public.ft2
5110 Remote SQL: DELETE FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 5)) RETURNING "C 1", c4
5113 DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4;
5115 ------+------------------------------
5116 5 | Tue Jan 06 00:00:00 1970 PST
5117 15 | Fri Jan 16 00:00:00 1970 PST
5118 25 | Mon Jan 26 00:00:00 1970 PST
5119 35 | Thu Feb 05 00:00:00 1970 PST
5120 45 | Sun Feb 15 00:00:00 1970 PST
5121 55 | Wed Feb 25 00:00:00 1970 PST
5122 65 | Sat Mar 07 00:00:00 1970 PST
5123 75 | Tue Mar 17 00:00:00 1970 PST
5124 85 | Fri Mar 27 00:00:00 1970 PST
5125 95 | Mon Apr 06 00:00:00 1970 PST
5126 105 | Tue Jan 06 00:00:00 1970 PST
5127 115 | Fri Jan 16 00:00:00 1970 PST
5128 125 | Mon Jan 26 00:00:00 1970 PST
5129 135 | Thu Feb 05 00:00:00 1970 PST
5130 145 | Sun Feb 15 00:00:00 1970 PST
5131 155 | Wed Feb 25 00:00:00 1970 PST
5132 165 | Sat Mar 07 00:00:00 1970 PST
5133 175 | Tue Mar 17 00:00:00 1970 PST
5134 185 | Fri Mar 27 00:00:00 1970 PST
5135 195 | Mon Apr 06 00:00:00 1970 PST
5136 205 | Tue Jan 06 00:00:00 1970 PST
5137 215 | Fri Jan 16 00:00:00 1970 PST
5138 225 | Mon Jan 26 00:00:00 1970 PST
5139 235 | Thu Feb 05 00:00:00 1970 PST
5140 245 | Sun Feb 15 00:00:00 1970 PST
5141 255 | Wed Feb 25 00:00:00 1970 PST
5142 265 | Sat Mar 07 00:00:00 1970 PST
5143 275 | Tue Mar 17 00:00:00 1970 PST
5144 285 | Fri Mar 27 00:00:00 1970 PST
5145 295 | Mon Apr 06 00:00:00 1970 PST
5146 305 | Tue Jan 06 00:00:00 1970 PST
5147 315 | Fri Jan 16 00:00:00 1970 PST
5148 325 | Mon Jan 26 00:00:00 1970 PST
5149 335 | Thu Feb 05 00:00:00 1970 PST
5150 345 | Sun Feb 15 00:00:00 1970 PST
5151 355 | Wed Feb 25 00:00:00 1970 PST
5152 365 | Sat Mar 07 00:00:00 1970 PST
5153 375 | Tue Mar 17 00:00:00 1970 PST
5154 385 | Fri Mar 27 00:00:00 1970 PST
5155 395 | Mon Apr 06 00:00:00 1970 PST
5156 405 | Tue Jan 06 00:00:00 1970 PST
5157 415 | Fri Jan 16 00:00:00 1970 PST
5158 425 | Mon Jan 26 00:00:00 1970 PST
5159 435 | Thu Feb 05 00:00:00 1970 PST
5160 445 | Sun Feb 15 00:00:00 1970 PST
5161 455 | Wed Feb 25 00:00:00 1970 PST
5162 465 | Sat Mar 07 00:00:00 1970 PST
5163 475 | Tue Mar 17 00:00:00 1970 PST
5164 485 | Fri Mar 27 00:00:00 1970 PST
5165 495 | Mon Apr 06 00:00:00 1970 PST
5166 505 | Tue Jan 06 00:00:00 1970 PST
5167 515 | Fri Jan 16 00:00:00 1970 PST
5168 525 | Mon Jan 26 00:00:00 1970 PST
5169 535 | Thu Feb 05 00:00:00 1970 PST
5170 545 | Sun Feb 15 00:00:00 1970 PST
5171 555 | Wed Feb 25 00:00:00 1970 PST
5172 565 | Sat Mar 07 00:00:00 1970 PST
5173 575 | Tue Mar 17 00:00:00 1970 PST
5174 585 | Fri Mar 27 00:00:00 1970 PST
5175 595 | Mon Apr 06 00:00:00 1970 PST
5176 605 | Tue Jan 06 00:00:00 1970 PST
5177 615 | Fri Jan 16 00:00:00 1970 PST
5178 625 | Mon Jan 26 00:00:00 1970 PST
5179 635 | Thu Feb 05 00:00:00 1970 PST
5180 645 | Sun Feb 15 00:00:00 1970 PST
5181 655 | Wed Feb 25 00:00:00 1970 PST
5182 665 | Sat Mar 07 00:00:00 1970 PST
5183 675 | Tue Mar 17 00:00:00 1970 PST
5184 685 | Fri Mar 27 00:00:00 1970 PST
5185 695 | Mon Apr 06 00:00:00 1970 PST
5186 705 | Tue Jan 06 00:00:00 1970 PST
5187 715 | Fri Jan 16 00:00:00 1970 PST
5188 725 | Mon Jan 26 00:00:00 1970 PST
5189 735 | Thu Feb 05 00:00:00 1970 PST
5190 745 | Sun Feb 15 00:00:00 1970 PST
5191 755 | Wed Feb 25 00:00:00 1970 PST
5192 765 | Sat Mar 07 00:00:00 1970 PST
5193 775 | Tue Mar 17 00:00:00 1970 PST
5194 785 | Fri Mar 27 00:00:00 1970 PST
5195 795 | Mon Apr 06 00:00:00 1970 PST
5196 805 | Tue Jan 06 00:00:00 1970 PST
5197 815 | Fri Jan 16 00:00:00 1970 PST
5198 825 | Mon Jan 26 00:00:00 1970 PST
5199 835 | Thu Feb 05 00:00:00 1970 PST
5200 845 | Sun Feb 15 00:00:00 1970 PST
5201 855 | Wed Feb 25 00:00:00 1970 PST
5202 865 | Sat Mar 07 00:00:00 1970 PST
5203 875 | Tue Mar 17 00:00:00 1970 PST
5204 885 | Fri Mar 27 00:00:00 1970 PST
5205 895 | Mon Apr 06 00:00:00 1970 PST
5206 905 | Tue Jan 06 00:00:00 1970 PST
5207 915 | Fri Jan 16 00:00:00 1970 PST
5208 925 | Mon Jan 26 00:00:00 1970 PST
5209 935 | Thu Feb 05 00:00:00 1970 PST
5210 945 | Sun Feb 15 00:00:00 1970 PST
5211 955 | Wed Feb 25 00:00:00 1970 PST
5212 965 | Sat Mar 07 00:00:00 1970 PST
5213 975 | Tue Mar 17 00:00:00 1970 PST
5214 985 | Fri Mar 27 00:00:00 1970 PST
5215 995 | Mon Apr 06 00:00:00 1970 PST
5221 EXPLAIN (verbose, costs off)
5222 DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2; -- can be pushed down
5224 ----------------------------------------------------------------------------------------------------------------------------
5225 Delete on public.ft2
5227 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))
5230 DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;
5231 SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1;
5233 ------+-----+--------------------+------------------------------
5234 1 | 1 | 00001 | Fri Jan 02 00:00:00 1970 PST
5235 3 | 303 | 00003_update3 | Sun Jan 04 00:00:00 1970 PST
5236 4 | 4 | 00004 | Mon Jan 05 00:00:00 1970 PST
5237 6 | 6 | 00006 | Wed Jan 07 00:00:00 1970 PST
5238 7 | 407 | 00007_update7 | Thu Jan 08 00:00:00 1970 PST
5239 8 | 8 | 00008 | Fri Jan 09 00:00:00 1970 PST
5240 9 | 509 | 00009_update9 | Sat Jan 10 00:00:00 1970 PST
5241 10 | 0 | 00010 | Sun Jan 11 00:00:00 1970 PST
5242 11 | 1 | 00011 | Mon Jan 12 00:00:00 1970 PST
5243 13 | 303 | 00013_update3 | Wed Jan 14 00:00:00 1970 PST
5244 14 | 4 | 00014 | Thu Jan 15 00:00:00 1970 PST
5245 16 | 6 | 00016 | Sat Jan 17 00:00:00 1970 PST
5246 17 | 407 | 00017_update7 | Sun Jan 18 00:00:00 1970 PST
5247 18 | 8 | 00018 | Mon Jan 19 00:00:00 1970 PST
5248 19 | 509 | 00019_update9 | Tue Jan 20 00:00:00 1970 PST
5249 20 | 0 | 00020 | Wed Jan 21 00:00:00 1970 PST
5250 21 | 1 | 00021 | Thu Jan 22 00:00:00 1970 PST
5251 23 | 303 | 00023_update3 | Sat Jan 24 00:00:00 1970 PST
5252 24 | 4 | 00024 | Sun Jan 25 00:00:00 1970 PST
5253 26 | 6 | 00026 | Tue Jan 27 00:00:00 1970 PST
5254 27 | 407 | 00027_update7 | Wed Jan 28 00:00:00 1970 PST
5255 28 | 8 | 00028 | Thu Jan 29 00:00:00 1970 PST
5256 29 | 509 | 00029_update9 | Fri Jan 30 00:00:00 1970 PST
5257 30 | 0 | 00030 | Sat Jan 31 00:00:00 1970 PST
5258 31 | 1 | 00031 | Sun Feb 01 00:00:00 1970 PST
5259 33 | 303 | 00033_update3 | Tue Feb 03 00:00:00 1970 PST
5260 34 | 4 | 00034 | Wed Feb 04 00:00:00 1970 PST
5261 36 | 6 | 00036 | Fri Feb 06 00:00:00 1970 PST
5262 37 | 407 | 00037_update7 | Sat Feb 07 00:00:00 1970 PST
5263 38 | 8 | 00038 | Sun Feb 08 00:00:00 1970 PST
5264 39 | 509 | 00039_update9 | Mon Feb 09 00:00:00 1970 PST
5265 40 | 0 | 00040 | Tue Feb 10 00:00:00 1970 PST
5266 41 | 1 | 00041 | Wed Feb 11 00:00:00 1970 PST
5267 43 | 303 | 00043_update3 | Fri Feb 13 00:00:00 1970 PST
5268 44 | 4 | 00044 | Sat Feb 14 00:00:00 1970 PST
5269 46 | 6 | 00046 | Mon Feb 16 00:00:00 1970 PST
5270 47 | 407 | 00047_update7 | Tue Feb 17 00:00:00 1970 PST
5271 48 | 8 | 00048 | Wed Feb 18 00:00:00 1970 PST
5272 49 | 509 | 00049_update9 | Thu Feb 19 00:00:00 1970 PST
5273 50 | 0 | 00050 | Fri Feb 20 00:00:00 1970 PST
5274 51 | 1 | 00051 | Sat Feb 21 00:00:00 1970 PST
5275 53 | 303 | 00053_update3 | Mon Feb 23 00:00:00 1970 PST
5276 54 | 4 | 00054 | Tue Feb 24 00:00:00 1970 PST
5277 56 | 6 | 00056 | Thu Feb 26 00:00:00 1970 PST
5278 57 | 407 | 00057_update7 | Fri Feb 27 00:00:00 1970 PST
5279 58 | 8 | 00058 | Sat Feb 28 00:00:00 1970 PST
5280 59 | 509 | 00059_update9 | Sun Mar 01 00:00:00 1970 PST
5281 60 | 0 | 00060 | Mon Mar 02 00:00:00 1970 PST
5282 61 | 1 | 00061 | Tue Mar 03 00:00:00 1970 PST
5283 63 | 303 | 00063_update3 | Thu Mar 05 00:00:00 1970 PST
5284 64 | 4 | 00064 | Fri Mar 06 00:00:00 1970 PST
5285 66 | 6 | 00066 | Sun Mar 08 00:00:00 1970 PST
5286 67 | 407 | 00067_update7 | Mon Mar 09 00:00:00 1970 PST
5287 68 | 8 | 00068 | Tue Mar 10 00:00:00 1970 PST
5288 69 | 509 | 00069_update9 | Wed Mar 11 00:00:00 1970 PST
5289 70 | 0 | 00070 | Thu Mar 12 00:00:00 1970 PST
5290 71 | 1 | 00071 | Fri Mar 13 00:00:00 1970 PST
5291 73 | 303 | 00073_update3 | Sun Mar 15 00:00:00 1970 PST
5292 74 | 4 | 00074 | Mon Mar 16 00:00:00 1970 PST
5293 76 | 6 | 00076 | Wed Mar 18 00:00:00 1970 PST
5294 77 | 407 | 00077_update7 | Thu Mar 19 00:00:00 1970 PST
5295 78 | 8 | 00078 | Fri Mar 20 00:00:00 1970 PST
5296 79 | 509 | 00079_update9 | Sat Mar 21 00:00:00 1970 PST
5297 80 | 0 | 00080 | Sun Mar 22 00:00:00 1970 PST
5298 81 | 1 | 00081 | Mon Mar 23 00:00:00 1970 PST
5299 83 | 303 | 00083_update3 | Wed Mar 25 00:00:00 1970 PST
5300 84 | 4 | 00084 | Thu Mar 26 00:00:00 1970 PST
5301 86 | 6 | 00086 | Sat Mar 28 00:00:00 1970 PST
5302 87 | 407 | 00087_update7 | Sun Mar 29 00:00:00 1970 PST
5303 88 | 8 | 00088 | Mon Mar 30 00:00:00 1970 PST
5304 89 | 509 | 00089_update9 | Tue Mar 31 00:00:00 1970 PST
5305 90 | 0 | 00090 | Wed Apr 01 00:00:00 1970 PST
5306 91 | 1 | 00091 | Thu Apr 02 00:00:00 1970 PST
5307 93 | 303 | 00093_update3 | Sat Apr 04 00:00:00 1970 PST
5308 94 | 4 | 00094 | Sun Apr 05 00:00:00 1970 PST
5309 96 | 6 | 00096 | Tue Apr 07 00:00:00 1970 PST
5310 97 | 407 | 00097_update7 | Wed Apr 08 00:00:00 1970 PST
5311 98 | 8 | 00098 | Thu Apr 09 00:00:00 1970 PST
5312 99 | 509 | 00099_update9 | Fri Apr 10 00:00:00 1970 PST
5313 100 | 0 | 00100 | Thu Jan 01 00:00:00 1970 PST
5314 101 | 1 | 00101 | Fri Jan 02 00:00:00 1970 PST
5315 103 | 303 | 00103_update3 | Sun Jan 04 00:00:00 1970 PST
5316 104 | 4 | 00104 | Mon Jan 05 00:00:00 1970 PST
5317 106 | 6 | 00106 | Wed Jan 07 00:00:00 1970 PST
5318 107 | 407 | 00107_update7 | Thu Jan 08 00:00:00 1970 PST
5319 108 | 8 | 00108 | Fri Jan 09 00:00:00 1970 PST
5320 109 | 509 | 00109_update9 | Sat Jan 10 00:00:00 1970 PST
5321 110 | 0 | 00110 | Sun Jan 11 00:00:00 1970 PST
5322 111 | 1 | 00111 | Mon Jan 12 00:00:00 1970 PST
5323 113 | 303 | 00113_update3 | Wed Jan 14 00:00:00 1970 PST
5324 114 | 4 | 00114 | Thu Jan 15 00:00:00 1970 PST
5325 116 | 6 | 00116 | Sat Jan 17 00:00:00 1970 PST
5326 117 | 407 | 00117_update7 | Sun Jan 18 00:00:00 1970 PST
5327 118 | 8 | 00118 | Mon Jan 19 00:00:00 1970 PST
5328 119 | 509 | 00119_update9 | Tue Jan 20 00:00:00 1970 PST
5329 120 | 0 | 00120 | Wed Jan 21 00:00:00 1970 PST
5330 121 | 1 | 00121 | Thu Jan 22 00:00:00 1970 PST
5331 123 | 303 | 00123_update3 | Sat Jan 24 00:00:00 1970 PST
5332 124 | 4 | 00124 | Sun Jan 25 00:00:00 1970 PST
5333 126 | 6 | 00126 | Tue Jan 27 00:00:00 1970 PST
5334 127 | 407 | 00127_update7 | Wed Jan 28 00:00:00 1970 PST
5335 128 | 8 | 00128 | Thu Jan 29 00:00:00 1970 PST
5336 129 | 509 | 00129_update9 | Fri Jan 30 00:00:00 1970 PST
5337 130 | 0 | 00130 | Sat Jan 31 00:00:00 1970 PST
5338 131 | 1 | 00131 | Sun Feb 01 00:00:00 1970 PST
5339 133 | 303 | 00133_update3 | Tue Feb 03 00:00:00 1970 PST
5340 134 | 4 | 00134 | Wed Feb 04 00:00:00 1970 PST
5341 136 | 6 | 00136 | Fri Feb 06 00:00:00 1970 PST
5342 137 | 407 | 00137_update7 | Sat Feb 07 00:00:00 1970 PST
5343 138 | 8 | 00138 | Sun Feb 08 00:00:00 1970 PST
5344 139 | 509 | 00139_update9 | Mon Feb 09 00:00:00 1970 PST
5345 140 | 0 | 00140 | Tue Feb 10 00:00:00 1970 PST
5346 141 | 1 | 00141 | Wed Feb 11 00:00:00 1970 PST
5347 143 | 303 | 00143_update3 | Fri Feb 13 00:00:00 1970 PST
5348 144 | 4 | 00144 | Sat Feb 14 00:00:00 1970 PST
5349 146 | 6 | 00146 | Mon Feb 16 00:00:00 1970 PST
5350 147 | 407 | 00147_update7 | Tue Feb 17 00:00:00 1970 PST
5351 148 | 8 | 00148 | Wed Feb 18 00:00:00 1970 PST
5352 149 | 509 | 00149_update9 | Thu Feb 19 00:00:00 1970 PST
5353 150 | 0 | 00150 | Fri Feb 20 00:00:00 1970 PST
5354 151 | 1 | 00151 | Sat Feb 21 00:00:00 1970 PST
5355 153 | 303 | 00153_update3 | Mon Feb 23 00:00:00 1970 PST
5356 154 | 4 | 00154 | Tue Feb 24 00:00:00 1970 PST
5357 156 | 6 | 00156 | Thu Feb 26 00:00:00 1970 PST
5358 157 | 407 | 00157_update7 | Fri Feb 27 00:00:00 1970 PST
5359 158 | 8 | 00158 | Sat Feb 28 00:00:00 1970 PST
5360 159 | 509 | 00159_update9 | Sun Mar 01 00:00:00 1970 PST
5361 160 | 0 | 00160 | Mon Mar 02 00:00:00 1970 PST
5362 161 | 1 | 00161 | Tue Mar 03 00:00:00 1970 PST
5363 163 | 303 | 00163_update3 | Thu Mar 05 00:00:00 1970 PST
5364 164 | 4 | 00164 | Fri Mar 06 00:00:00 1970 PST
5365 166 | 6 | 00166 | Sun Mar 08 00:00:00 1970 PST
5366 167 | 407 | 00167_update7 | Mon Mar 09 00:00:00 1970 PST
5367 168 | 8 | 00168 | Tue Mar 10 00:00:00 1970 PST
5368 169 | 509 | 00169_update9 | Wed Mar 11 00:00:00 1970 PST
5369 170 | 0 | 00170 | Thu Mar 12 00:00:00 1970 PST
5370 171 | 1 | 00171 | Fri Mar 13 00:00:00 1970 PST
5371 173 | 303 | 00173_update3 | Sun Mar 15 00:00:00 1970 PST
5372 174 | 4 | 00174 | Mon Mar 16 00:00:00 1970 PST
5373 176 | 6 | 00176 | Wed Mar 18 00:00:00 1970 PST
5374 177 | 407 | 00177_update7 | Thu Mar 19 00:00:00 1970 PST
5375 178 | 8 | 00178 | Fri Mar 20 00:00:00 1970 PST
5376 179 | 509 | 00179_update9 | Sat Mar 21 00:00:00 1970 PST
5377 180 | 0 | 00180 | Sun Mar 22 00:00:00 1970 PST
5378 181 | 1 | 00181 | Mon Mar 23 00:00:00 1970 PST
5379 183 | 303 | 00183_update3 | Wed Mar 25 00:00:00 1970 PST
5380 184 | 4 | 00184 | Thu Mar 26 00:00:00 1970 PST
5381 186 | 6 | 00186 | Sat Mar 28 00:00:00 1970 PST
5382 187 | 407 | 00187_update7 | Sun Mar 29 00:00:00 1970 PST
5383 188 | 8 | 00188 | Mon Mar 30 00:00:00 1970 PST
5384 189 | 509 | 00189_update9 | Tue Mar 31 00:00:00 1970 PST
5385 190 | 0 | 00190 | Wed Apr 01 00:00:00 1970 PST
5386 191 | 1 | 00191 | Thu Apr 02 00:00:00 1970 PST
5387 193 | 303 | 00193_update3 | Sat Apr 04 00:00:00 1970 PST
5388 194 | 4 | 00194 | Sun Apr 05 00:00:00 1970 PST
5389 196 | 6 | 00196 | Tue Apr 07 00:00:00 1970 PST
5390 197 | 407 | 00197_update7 | Wed Apr 08 00:00:00 1970 PST
5391 198 | 8 | 00198 | Thu Apr 09 00:00:00 1970 PST
5392 199 | 509 | 00199_update9 | Fri Apr 10 00:00:00 1970 PST
5393 200 | 0 | 00200 | Thu Jan 01 00:00:00 1970 PST
5394 201 | 1 | 00201 | Fri Jan 02 00:00:00 1970 PST
5395 203 | 303 | 00203_update3 | Sun Jan 04 00:00:00 1970 PST
5396 204 | 4 | 00204 | Mon Jan 05 00:00:00 1970 PST
5397 206 | 6 | 00206 | Wed Jan 07 00:00:00 1970 PST
5398 207 | 407 | 00207_update7 | Thu Jan 08 00:00:00 1970 PST
5399 208 | 8 | 00208 | Fri Jan 09 00:00:00 1970 PST
5400 209 | 509 | 00209_update9 | Sat Jan 10 00:00:00 1970 PST
5401 210 | 0 | 00210 | Sun Jan 11 00:00:00 1970 PST
5402 211 | 1 | 00211 | Mon Jan 12 00:00:00 1970 PST
5403 213 | 303 | 00213_update3 | Wed Jan 14 00:00:00 1970 PST
5404 214 | 4 | 00214 | Thu Jan 15 00:00:00 1970 PST
5405 216 | 6 | 00216 | Sat Jan 17 00:00:00 1970 PST
5406 217 | 407 | 00217_update7 | Sun Jan 18 00:00:00 1970 PST
5407 218 | 8 | 00218 | Mon Jan 19 00:00:00 1970 PST
5408 219 | 509 | 00219_update9 | Tue Jan 20 00:00:00 1970 PST
5409 220 | 0 | 00220 | Wed Jan 21 00:00:00 1970 PST
5410 221 | 1 | 00221 | Thu Jan 22 00:00:00 1970 PST
5411 223 | 303 | 00223_update3 | Sat Jan 24 00:00:00 1970 PST
5412 224 | 4 | 00224 | Sun Jan 25 00:00:00 1970 PST
5413 226 | 6 | 00226 | Tue Jan 27 00:00:00 1970 PST
5414 227 | 407 | 00227_update7 | Wed Jan 28 00:00:00 1970 PST
5415 228 | 8 | 00228 | Thu Jan 29 00:00:00 1970 PST
5416 229 | 509 | 00229_update9 | Fri Jan 30 00:00:00 1970 PST
5417 230 | 0 | 00230 | Sat Jan 31 00:00:00 1970 PST
5418 231 | 1 | 00231 | Sun Feb 01 00:00:00 1970 PST
5419 233 | 303 | 00233_update3 | Tue Feb 03 00:00:00 1970 PST
5420 234 | 4 | 00234 | Wed Feb 04 00:00:00 1970 PST
5421 236 | 6 | 00236 | Fri Feb 06 00:00:00 1970 PST
5422 237 | 407 | 00237_update7 | Sat Feb 07 00:00:00 1970 PST
5423 238 | 8 | 00238 | Sun Feb 08 00:00:00 1970 PST
5424 239 | 509 | 00239_update9 | Mon Feb 09 00:00:00 1970 PST
5425 240 | 0 | 00240 | Tue Feb 10 00:00:00 1970 PST
5426 241 | 1 | 00241 | Wed Feb 11 00:00:00 1970 PST
5427 243 | 303 | 00243_update3 | Fri Feb 13 00:00:00 1970 PST
5428 244 | 4 | 00244 | Sat Feb 14 00:00:00 1970 PST
5429 246 | 6 | 00246 | Mon Feb 16 00:00:00 1970 PST
5430 247 | 407 | 00247_update7 | Tue Feb 17 00:00:00 1970 PST
5431 248 | 8 | 00248 | Wed Feb 18 00:00:00 1970 PST
5432 249 | 509 | 00249_update9 | Thu Feb 19 00:00:00 1970 PST
5433 250 | 0 | 00250 | Fri Feb 20 00:00:00 1970 PST
5434 251 | 1 | 00251 | Sat Feb 21 00:00:00 1970 PST
5435 253 | 303 | 00253_update3 | Mon Feb 23 00:00:00 1970 PST
5436 254 | 4 | 00254 | Tue Feb 24 00:00:00 1970 PST
5437 256 | 6 | 00256 | Thu Feb 26 00:00:00 1970 PST
5438 257 | 407 | 00257_update7 | Fri Feb 27 00:00:00 1970 PST
5439 258 | 8 | 00258 | Sat Feb 28 00:00:00 1970 PST
5440 259 | 509 | 00259_update9 | Sun Mar 01 00:00:00 1970 PST
5441 260 | 0 | 00260 | Mon Mar 02 00:00:00 1970 PST
5442 261 | 1 | 00261 | Tue Mar 03 00:00:00 1970 PST
5443 263 | 303 | 00263_update3 | Thu Mar 05 00:00:00 1970 PST
5444 264 | 4 | 00264 | Fri Mar 06 00:00:00 1970 PST
5445 266 | 6 | 00266 | Sun Mar 08 00:00:00 1970 PST
5446 267 | 407 | 00267_update7 | Mon Mar 09 00:00:00 1970 PST
5447 268 | 8 | 00268 | Tue Mar 10 00:00:00 1970 PST
5448 269 | 509 | 00269_update9 | Wed Mar 11 00:00:00 1970 PST
5449 270 | 0 | 00270 | Thu Mar 12 00:00:00 1970 PST
5450 271 | 1 | 00271 | Fri Mar 13 00:00:00 1970 PST
5451 273 | 303 | 00273_update3 | Sun Mar 15 00:00:00 1970 PST
5452 274 | 4 | 00274 | Mon Mar 16 00:00:00 1970 PST
5453 276 | 6 | 00276 | Wed Mar 18 00:00:00 1970 PST
5454 277 | 407 | 00277_update7 | Thu Mar 19 00:00:00 1970 PST
5455 278 | 8 | 00278 | Fri Mar 20 00:00:00 1970 PST
5456 279 | 509 | 00279_update9 | Sat Mar 21 00:00:00 1970 PST
5457 280 | 0 | 00280 | Sun Mar 22 00:00:00 1970 PST
5458 281 | 1 | 00281 | Mon Mar 23 00:00:00 1970 PST
5459 283 | 303 | 00283_update3 | Wed Mar 25 00:00:00 1970 PST
5460 284 | 4 | 00284 | Thu Mar 26 00:00:00 1970 PST
5461 286 | 6 | 00286 | Sat Mar 28 00:00:00 1970 PST
5462 287 | 407 | 00287_update7 | Sun Mar 29 00:00:00 1970 PST
5463 288 | 8 | 00288 | Mon Mar 30 00:00:00 1970 PST
5464 289 | 509 | 00289_update9 | Tue Mar 31 00:00:00 1970 PST
5465 290 | 0 | 00290 | Wed Apr 01 00:00:00 1970 PST
5466 291 | 1 | 00291 | Thu Apr 02 00:00:00 1970 PST
5467 293 | 303 | 00293_update3 | Sat Apr 04 00:00:00 1970 PST
5468 294 | 4 | 00294 | Sun Apr 05 00:00:00 1970 PST
5469 296 | 6 | 00296 | Tue Apr 07 00:00:00 1970 PST
5470 297 | 407 | 00297_update7 | Wed Apr 08 00:00:00 1970 PST
5471 298 | 8 | 00298 | Thu Apr 09 00:00:00 1970 PST
5472 299 | 509 | 00299_update9 | Fri Apr 10 00:00:00 1970 PST
5473 300 | 0 | 00300 | Thu Jan 01 00:00:00 1970 PST
5474 301 | 1 | 00301 | Fri Jan 02 00:00:00 1970 PST
5475 303 | 303 | 00303_update3 | Sun Jan 04 00:00:00 1970 PST
5476 304 | 4 | 00304 | Mon Jan 05 00:00:00 1970 PST
5477 306 | 6 | 00306 | Wed Jan 07 00:00:00 1970 PST
5478 307 | 407 | 00307_update7 | Thu Jan 08 00:00:00 1970 PST
5479 308 | 8 | 00308 | Fri Jan 09 00:00:00 1970 PST
5480 309 | 509 | 00309_update9 | Sat Jan 10 00:00:00 1970 PST
5481 310 | 0 | 00310 | Sun Jan 11 00:00:00 1970 PST
5482 311 | 1 | 00311 | Mon Jan 12 00:00:00 1970 PST
5483 313 | 303 | 00313_update3 | Wed Jan 14 00:00:00 1970 PST
5484 314 | 4 | 00314 | Thu Jan 15 00:00:00 1970 PST
5485 316 | 6 | 00316 | Sat Jan 17 00:00:00 1970 PST
5486 317 | 407 | 00317_update7 | Sun Jan 18 00:00:00 1970 PST
5487 318 | 8 | 00318 | Mon Jan 19 00:00:00 1970 PST
5488 319 | 509 | 00319_update9 | Tue Jan 20 00:00:00 1970 PST
5489 320 | 0 | 00320 | Wed Jan 21 00:00:00 1970 PST
5490 321 | 1 | 00321 | Thu Jan 22 00:00:00 1970 PST
5491 323 | 303 | 00323_update3 | Sat Jan 24 00:00:00 1970 PST
5492 324 | 4 | 00324 | Sun Jan 25 00:00:00 1970 PST
5493 326 | 6 | 00326 | Tue Jan 27 00:00:00 1970 PST
5494 327 | 407 | 00327_update7 | Wed Jan 28 00:00:00 1970 PST
5495 328 | 8 | 00328 | Thu Jan 29 00:00:00 1970 PST
5496 329 | 509 | 00329_update9 | Fri Jan 30 00:00:00 1970 PST
5497 330 | 0 | 00330 | Sat Jan 31 00:00:00 1970 PST
5498 331 | 1 | 00331 | Sun Feb 01 00:00:00 1970 PST
5499 333 | 303 | 00333_update3 | Tue Feb 03 00:00:00 1970 PST
5500 334 | 4 | 00334 | Wed Feb 04 00:00:00 1970 PST
5501 336 | 6 | 00336 | Fri Feb 06 00:00:00 1970 PST
5502 337 | 407 | 00337_update7 | Sat Feb 07 00:00:00 1970 PST
5503 338 | 8 | 00338 | Sun Feb 08 00:00:00 1970 PST
5504 339 | 509 | 00339_update9 | Mon Feb 09 00:00:00 1970 PST
5505 340 | 0 | 00340 | Tue Feb 10 00:00:00 1970 PST
5506 341 | 1 | 00341 | Wed Feb 11 00:00:00 1970 PST
5507 343 | 303 | 00343_update3 | Fri Feb 13 00:00:00 1970 PST
5508 344 | 4 | 00344 | Sat Feb 14 00:00:00 1970 PST
5509 346 | 6 | 00346 | Mon Feb 16 00:00:00 1970 PST
5510 347 | 407 | 00347_update7 | Tue Feb 17 00:00:00 1970 PST
5511 348 | 8 | 00348 | Wed Feb 18 00:00:00 1970 PST
5512 349 | 509 | 00349_update9 | Thu Feb 19 00:00:00 1970 PST
5513 350 | 0 | 00350 | Fri Feb 20 00:00:00 1970 PST
5514 351 | 1 | 00351 | Sat Feb 21 00:00:00 1970 PST
5515 353 | 303 | 00353_update3 | Mon Feb 23 00:00:00 1970 PST
5516 354 | 4 | 00354 | Tue Feb 24 00:00:00 1970 PST
5517 356 | 6 | 00356 | Thu Feb 26 00:00:00 1970 PST
5518 357 | 407 | 00357_update7 | Fri Feb 27 00:00:00 1970 PST
5519 358 | 8 | 00358 | Sat Feb 28 00:00:00 1970 PST
5520 359 | 509 | 00359_update9 | Sun Mar 01 00:00:00 1970 PST
5521 360 | 0 | 00360 | Mon Mar 02 00:00:00 1970 PST
5522 361 | 1 | 00361 | Tue Mar 03 00:00:00 1970 PST
5523 363 | 303 | 00363_update3 | Thu Mar 05 00:00:00 1970 PST
5524 364 | 4 | 00364 | Fri Mar 06 00:00:00 1970 PST
5525 366 | 6 | 00366 | Sun Mar 08 00:00:00 1970 PST
5526 367 | 407 | 00367_update7 | Mon Mar 09 00:00:00 1970 PST
5527 368 | 8 | 00368 | Tue Mar 10 00:00:00 1970 PST
5528 369 | 509 | 00369_update9 | Wed Mar 11 00:00:00 1970 PST
5529 370 | 0 | 00370 | Thu Mar 12 00:00:00 1970 PST
5530 371 | 1 | 00371 | Fri Mar 13 00:00:00 1970 PST
5531 373 | 303 | 00373_update3 | Sun Mar 15 00:00:00 1970 PST
5532 374 | 4 | 00374 | Mon Mar 16 00:00:00 1970 PST
5533 376 | 6 | 00376 | Wed Mar 18 00:00:00 1970 PST
5534 377 | 407 | 00377_update7 | Thu Mar 19 00:00:00 1970 PST
5535 378 | 8 | 00378 | Fri Mar 20 00:00:00 1970 PST
5536 379 | 509 | 00379_update9 | Sat Mar 21 00:00:00 1970 PST
5537 380 | 0 | 00380 | Sun Mar 22 00:00:00 1970 PST
5538 381 | 1 | 00381 | Mon Mar 23 00:00:00 1970 PST
5539 383 | 303 | 00383_update3 | Wed Mar 25 00:00:00 1970 PST
5540 384 | 4 | 00384 | Thu Mar 26 00:00:00 1970 PST
5541 386 | 6 | 00386 | Sat Mar 28 00:00:00 1970 PST
5542 387 | 407 | 00387_update7 | Sun Mar 29 00:00:00 1970 PST
5543 388 | 8 | 00388 | Mon Mar 30 00:00:00 1970 PST
5544 389 | 509 | 00389_update9 | Tue Mar 31 00:00:00 1970 PST
5545 390 | 0 | 00390 | Wed Apr 01 00:00:00 1970 PST
5546 391 | 1 | 00391 | Thu Apr 02 00:00:00 1970 PST
5547 393 | 303 | 00393_update3 | Sat Apr 04 00:00:00 1970 PST
5548 394 | 4 | 00394 | Sun Apr 05 00:00:00 1970 PST
5549 396 | 6 | 00396 | Tue Apr 07 00:00:00 1970 PST
5550 397 | 407 | 00397_update7 | Wed Apr 08 00:00:00 1970 PST
5551 398 | 8 | 00398 | Thu Apr 09 00:00:00 1970 PST
5552 399 | 509 | 00399_update9 | Fri Apr 10 00:00:00 1970 PST
5553 400 | 0 | 00400 | Thu Jan 01 00:00:00 1970 PST
5554 401 | 1 | 00401 | Fri Jan 02 00:00:00 1970 PST
5555 403 | 303 | 00403_update3 | Sun Jan 04 00:00:00 1970 PST
5556 404 | 4 | 00404 | Mon Jan 05 00:00:00 1970 PST
5557 406 | 6 | 00406 | Wed Jan 07 00:00:00 1970 PST
5558 407 | 407 | 00407_update7 | Thu Jan 08 00:00:00 1970 PST
5559 408 | 8 | 00408 | Fri Jan 09 00:00:00 1970 PST
5560 409 | 509 | 00409_update9 | Sat Jan 10 00:00:00 1970 PST
5561 410 | 0 | 00410 | Sun Jan 11 00:00:00 1970 PST
5562 411 | 1 | 00411 | Mon Jan 12 00:00:00 1970 PST
5563 413 | 303 | 00413_update3 | Wed Jan 14 00:00:00 1970 PST
5564 414 | 4 | 00414 | Thu Jan 15 00:00:00 1970 PST
5565 416 | 6 | 00416 | Sat Jan 17 00:00:00 1970 PST
5566 417 | 407 | 00417_update7 | Sun Jan 18 00:00:00 1970 PST
5567 418 | 8 | 00418 | Mon Jan 19 00:00:00 1970 PST
5568 419 | 509 | 00419_update9 | Tue Jan 20 00:00:00 1970 PST
5569 420 | 0 | 00420 | Wed Jan 21 00:00:00 1970 PST
5570 421 | 1 | 00421 | Thu Jan 22 00:00:00 1970 PST
5571 423 | 303 | 00423_update3 | Sat Jan 24 00:00:00 1970 PST
5572 424 | 4 | 00424 | Sun Jan 25 00:00:00 1970 PST
5573 426 | 6 | 00426 | Tue Jan 27 00:00:00 1970 PST
5574 427 | 407 | 00427_update7 | Wed Jan 28 00:00:00 1970 PST
5575 428 | 8 | 00428 | Thu Jan 29 00:00:00 1970 PST
5576 429 | 509 | 00429_update9 | Fri Jan 30 00:00:00 1970 PST
5577 430 | 0 | 00430 | Sat Jan 31 00:00:00 1970 PST
5578 431 | 1 | 00431 | Sun Feb 01 00:00:00 1970 PST
5579 433 | 303 | 00433_update3 | Tue Feb 03 00:00:00 1970 PST
5580 434 | 4 | 00434 | Wed Feb 04 00:00:00 1970 PST
5581 436 | 6 | 00436 | Fri Feb 06 00:00:00 1970 PST
5582 437 | 407 | 00437_update7 | Sat Feb 07 00:00:00 1970 PST
5583 438 | 8 | 00438 | Sun Feb 08 00:00:00 1970 PST
5584 439 | 509 | 00439_update9 | Mon Feb 09 00:00:00 1970 PST
5585 440 | 0 | 00440 | Tue Feb 10 00:00:00 1970 PST
5586 441 | 1 | 00441 | Wed Feb 11 00:00:00 1970 PST
5587 443 | 303 | 00443_update3 | Fri Feb 13 00:00:00 1970 PST
5588 444 | 4 | 00444 | Sat Feb 14 00:00:00 1970 PST
5589 446 | 6 | 00446 | Mon Feb 16 00:00:00 1970 PST
5590 447 | 407 | 00447_update7 | Tue Feb 17 00:00:00 1970 PST
5591 448 | 8 | 00448 | Wed Feb 18 00:00:00 1970 PST
5592 449 | 509 | 00449_update9 | Thu Feb 19 00:00:00 1970 PST
5593 450 | 0 | 00450 | Fri Feb 20 00:00:00 1970 PST
5594 451 | 1 | 00451 | Sat Feb 21 00:00:00 1970 PST
5595 453 | 303 | 00453_update3 | Mon Feb 23 00:00:00 1970 PST
5596 454 | 4 | 00454 | Tue Feb 24 00:00:00 1970 PST
5597 456 | 6 | 00456 | Thu Feb 26 00:00:00 1970 PST
5598 457 | 407 | 00457_update7 | Fri Feb 27 00:00:00 1970 PST
5599 458 | 8 | 00458 | Sat Feb 28 00:00:00 1970 PST
5600 459 | 509 | 00459_update9 | Sun Mar 01 00:00:00 1970 PST
5601 460 | 0 | 00460 | Mon Mar 02 00:00:00 1970 PST
5602 461 | 1 | 00461 | Tue Mar 03 00:00:00 1970 PST
5603 463 | 303 | 00463_update3 | Thu Mar 05 00:00:00 1970 PST
5604 464 | 4 | 00464 | Fri Mar 06 00:00:00 1970 PST
5605 466 | 6 | 00466 | Sun Mar 08 00:00:00 1970 PST
5606 467 | 407 | 00467_update7 | Mon Mar 09 00:00:00 1970 PST
5607 468 | 8 | 00468 | Tue Mar 10 00:00:00 1970 PST
5608 469 | 509 | 00469_update9 | Wed Mar 11 00:00:00 1970 PST
5609 470 | 0 | 00470 | Thu Mar 12 00:00:00 1970 PST
5610 471 | 1 | 00471 | Fri Mar 13 00:00:00 1970 PST
5611 473 | 303 | 00473_update3 | Sun Mar 15 00:00:00 1970 PST
5612 474 | 4 | 00474 | Mon Mar 16 00:00:00 1970 PST
5613 476 | 6 | 00476 | Wed Mar 18 00:00:00 1970 PST
5614 477 | 407 | 00477_update7 | Thu Mar 19 00:00:00 1970 PST
5615 478 | 8 | 00478 | Fri Mar 20 00:00:00 1970 PST
5616 479 | 509 | 00479_update9 | Sat Mar 21 00:00:00 1970 PST
5617 480 | 0 | 00480 | Sun Mar 22 00:00:00 1970 PST
5618 481 | 1 | 00481 | Mon Mar 23 00:00:00 1970 PST
5619 483 | 303 | 00483_update3 | Wed Mar 25 00:00:00 1970 PST
5620 484 | 4 | 00484 | Thu Mar 26 00:00:00 1970 PST
5621 486 | 6 | 00486 | Sat Mar 28 00:00:00 1970 PST
5622 487 | 407 | 00487_update7 | Sun Mar 29 00:00:00 1970 PST
5623 488 | 8 | 00488 | Mon Mar 30 00:00:00 1970 PST
5624 489 | 509 | 00489_update9 | Tue Mar 31 00:00:00 1970 PST
5625 490 | 0 | 00490 | Wed Apr 01 00:00:00 1970 PST
5626 491 | 1 | 00491 | Thu Apr 02 00:00:00 1970 PST
5627 493 | 303 | 00493_update3 | Sat Apr 04 00:00:00 1970 PST
5628 494 | 4 | 00494 | Sun Apr 05 00:00:00 1970 PST
5629 496 | 6 | 00496 | Tue Apr 07 00:00:00 1970 PST
5630 497 | 407 | 00497_update7 | Wed Apr 08 00:00:00 1970 PST
5631 498 | 8 | 00498 | Thu Apr 09 00:00:00 1970 PST
5632 499 | 509 | 00499_update9 | Fri Apr 10 00:00:00 1970 PST
5633 500 | 0 | 00500 | Thu Jan 01 00:00:00 1970 PST
5634 501 | 1 | 00501 | Fri Jan 02 00:00:00 1970 PST
5635 503 | 303 | 00503_update3 | Sun Jan 04 00:00:00 1970 PST
5636 504 | 4 | 00504 | Mon Jan 05 00:00:00 1970 PST
5637 506 | 6 | 00506 | Wed Jan 07 00:00:00 1970 PST
5638 507 | 407 | 00507_update7 | Thu Jan 08 00:00:00 1970 PST
5639 508 | 8 | 00508 | Fri Jan 09 00:00:00 1970 PST
5640 509 | 509 | 00509_update9 | Sat Jan 10 00:00:00 1970 PST
5641 510 | 0 | 00510 | Sun Jan 11 00:00:00 1970 PST
5642 511 | 1 | 00511 | Mon Jan 12 00:00:00 1970 PST
5643 513 | 303 | 00513_update3 | Wed Jan 14 00:00:00 1970 PST
5644 514 | 4 | 00514 | Thu Jan 15 00:00:00 1970 PST
5645 516 | 6 | 00516 | Sat Jan 17 00:00:00 1970 PST
5646 517 | 407 | 00517_update7 | Sun Jan 18 00:00:00 1970 PST
5647 518 | 8 | 00518 | Mon Jan 19 00:00:00 1970 PST
5648 519 | 509 | 00519_update9 | Tue Jan 20 00:00:00 1970 PST
5649 520 | 0 | 00520 | Wed Jan 21 00:00:00 1970 PST
5650 521 | 1 | 00521 | Thu Jan 22 00:00:00 1970 PST
5651 523 | 303 | 00523_update3 | Sat Jan 24 00:00:00 1970 PST
5652 524 | 4 | 00524 | Sun Jan 25 00:00:00 1970 PST
5653 526 | 6 | 00526 | Tue Jan 27 00:00:00 1970 PST
5654 527 | 407 | 00527_update7 | Wed Jan 28 00:00:00 1970 PST
5655 528 | 8 | 00528 | Thu Jan 29 00:00:00 1970 PST
5656 529 | 509 | 00529_update9 | Fri Jan 30 00:00:00 1970 PST
5657 530 | 0 | 00530 | Sat Jan 31 00:00:00 1970 PST
5658 531 | 1 | 00531 | Sun Feb 01 00:00:00 1970 PST
5659 533 | 303 | 00533_update3 | Tue Feb 03 00:00:00 1970 PST
5660 534 | 4 | 00534 | Wed Feb 04 00:00:00 1970 PST
5661 536 | 6 | 00536 | Fri Feb 06 00:00:00 1970 PST
5662 537 | 407 | 00537_update7 | Sat Feb 07 00:00:00 1970 PST
5663 538 | 8 | 00538 | Sun Feb 08 00:00:00 1970 PST
5664 539 | 509 | 00539_update9 | Mon Feb 09 00:00:00 1970 PST
5665 540 | 0 | 00540 | Tue Feb 10 00:00:00 1970 PST
5666 541 | 1 | 00541 | Wed Feb 11 00:00:00 1970 PST
5667 543 | 303 | 00543_update3 | Fri Feb 13 00:00:00 1970 PST
5668 544 | 4 | 00544 | Sat Feb 14 00:00:00 1970 PST
5669 546 | 6 | 00546 | Mon Feb 16 00:00:00 1970 PST
5670 547 | 407 | 00547_update7 | Tue Feb 17 00:00:00 1970 PST
5671 548 | 8 | 00548 | Wed Feb 18 00:00:00 1970 PST
5672 549 | 509 | 00549_update9 | Thu Feb 19 00:00:00 1970 PST
5673 550 | 0 | 00550 | Fri Feb 20 00:00:00 1970 PST
5674 551 | 1 | 00551 | Sat Feb 21 00:00:00 1970 PST
5675 553 | 303 | 00553_update3 | Mon Feb 23 00:00:00 1970 PST
5676 554 | 4 | 00554 | Tue Feb 24 00:00:00 1970 PST
5677 556 | 6 | 00556 | Thu Feb 26 00:00:00 1970 PST
5678 557 | 407 | 00557_update7 | Fri Feb 27 00:00:00 1970 PST
5679 558 | 8 | 00558 | Sat Feb 28 00:00:00 1970 PST
5680 559 | 509 | 00559_update9 | Sun Mar 01 00:00:00 1970 PST
5681 560 | 0 | 00560 | Mon Mar 02 00:00:00 1970 PST
5682 561 | 1 | 00561 | Tue Mar 03 00:00:00 1970 PST
5683 563 | 303 | 00563_update3 | Thu Mar 05 00:00:00 1970 PST
5684 564 | 4 | 00564 | Fri Mar 06 00:00:00 1970 PST
5685 566 | 6 | 00566 | Sun Mar 08 00:00:00 1970 PST
5686 567 | 407 | 00567_update7 | Mon Mar 09 00:00:00 1970 PST
5687 568 | 8 | 00568 | Tue Mar 10 00:00:00 1970 PST
5688 569 | 509 | 00569_update9 | Wed Mar 11 00:00:00 1970 PST
5689 570 | 0 | 00570 | Thu Mar 12 00:00:00 1970 PST
5690 571 | 1 | 00571 | Fri Mar 13 00:00:00 1970 PST
5691 573 | 303 | 00573_update3 | Sun Mar 15 00:00:00 1970 PST
5692 574 | 4 | 00574 | Mon Mar 16 00:00:00 1970 PST
5693 576 | 6 | 00576 | Wed Mar 18 00:00:00 1970 PST
5694 577 | 407 | 00577_update7 | Thu Mar 19 00:00:00 1970 PST
5695 578 | 8 | 00578 | Fri Mar 20 00:00:00 1970 PST
5696 579 | 509 | 00579_update9 | Sat Mar 21 00:00:00 1970 PST
5697 580 | 0 | 00580 | Sun Mar 22 00:00:00 1970 PST
5698 581 | 1 | 00581 | Mon Mar 23 00:00:00 1970 PST
5699 583 | 303 | 00583_update3 | Wed Mar 25 00:00:00 1970 PST
5700 584 | 4 | 00584 | Thu Mar 26 00:00:00 1970 PST
5701 586 | 6 | 00586 | Sat Mar 28 00:00:00 1970 PST
5702 587 | 407 | 00587_update7 | Sun Mar 29 00:00:00 1970 PST
5703 588 | 8 | 00588 | Mon Mar 30 00:00:00 1970 PST
5704 589 | 509 | 00589_update9 | Tue Mar 31 00:00:00 1970 PST
5705 590 | 0 | 00590 | Wed Apr 01 00:00:00 1970 PST
5706 591 | 1 | 00591 | Thu Apr 02 00:00:00 1970 PST
5707 593 | 303 | 00593_update3 | Sat Apr 04 00:00:00 1970 PST
5708 594 | 4 | 00594 | Sun Apr 05 00:00:00 1970 PST
5709 596 | 6 | 00596 | Tue Apr 07 00:00:00 1970 PST
5710 597 | 407 | 00597_update7 | Wed Apr 08 00:00:00 1970 PST
5711 598 | 8 | 00598 | Thu Apr 09 00:00:00 1970 PST
5712 599 | 509 | 00599_update9 | Fri Apr 10 00:00:00 1970 PST
5713 600 | 0 | 00600 | Thu Jan 01 00:00:00 1970 PST
5714 601 | 1 | 00601 | Fri Jan 02 00:00:00 1970 PST
5715 603 | 303 | 00603_update3 | Sun Jan 04 00:00:00 1970 PST
5716 604 | 4 | 00604 | Mon Jan 05 00:00:00 1970 PST
5717 606 | 6 | 00606 | Wed Jan 07 00:00:00 1970 PST
5718 607 | 407 | 00607_update7 | Thu Jan 08 00:00:00 1970 PST
5719 608 | 8 | 00608 | Fri Jan 09 00:00:00 1970 PST
5720 609 | 509 | 00609_update9 | Sat Jan 10 00:00:00 1970 PST
5721 610 | 0 | 00610 | Sun Jan 11 00:00:00 1970 PST
5722 611 | 1 | 00611 | Mon Jan 12 00:00:00 1970 PST
5723 613 | 303 | 00613_update3 | Wed Jan 14 00:00:00 1970 PST
5724 614 | 4 | 00614 | Thu Jan 15 00:00:00 1970 PST
5725 616 | 6 | 00616 | Sat Jan 17 00:00:00 1970 PST
5726 617 | 407 | 00617_update7 | Sun Jan 18 00:00:00 1970 PST
5727 618 | 8 | 00618 | Mon Jan 19 00:00:00 1970 PST
5728 619 | 509 | 00619_update9 | Tue Jan 20 00:00:00 1970 PST
5729 620 | 0 | 00620 | Wed Jan 21 00:00:00 1970 PST
5730 621 | 1 | 00621 | Thu Jan 22 00:00:00 1970 PST
5731 623 | 303 | 00623_update3 | Sat Jan 24 00:00:00 1970 PST
5732 624 | 4 | 00624 | Sun Jan 25 00:00:00 1970 PST
5733 626 | 6 | 00626 | Tue Jan 27 00:00:00 1970 PST
5734 627 | 407 | 00627_update7 | Wed Jan 28 00:00:00 1970 PST
5735 628 | 8 | 00628 | Thu Jan 29 00:00:00 1970 PST
5736 629 | 509 | 00629_update9 | Fri Jan 30 00:00:00 1970 PST
5737 630 | 0 | 00630 | Sat Jan 31 00:00:00 1970 PST
5738 631 | 1 | 00631 | Sun Feb 01 00:00:00 1970 PST
5739 633 | 303 | 00633_update3 | Tue Feb 03 00:00:00 1970 PST
5740 634 | 4 | 00634 | Wed Feb 04 00:00:00 1970 PST
5741 636 | 6 | 00636 | Fri Feb 06 00:00:00 1970 PST
5742 637 | 407 | 00637_update7 | Sat Feb 07 00:00:00 1970 PST
5743 638 | 8 | 00638 | Sun Feb 08 00:00:00 1970 PST
5744 639 | 509 | 00639_update9 | Mon Feb 09 00:00:00 1970 PST
5745 640 | 0 | 00640 | Tue Feb 10 00:00:00 1970 PST
5746 641 | 1 | 00641 | Wed Feb 11 00:00:00 1970 PST
5747 643 | 303 | 00643_update3 | Fri Feb 13 00:00:00 1970 PST
5748 644 | 4 | 00644 | Sat Feb 14 00:00:00 1970 PST
5749 646 | 6 | 00646 | Mon Feb 16 00:00:00 1970 PST
5750 647 | 407 | 00647_update7 | Tue Feb 17 00:00:00 1970 PST
5751 648 | 8 | 00648 | Wed Feb 18 00:00:00 1970 PST
5752 649 | 509 | 00649_update9 | Thu Feb 19 00:00:00 1970 PST
5753 650 | 0 | 00650 | Fri Feb 20 00:00:00 1970 PST
5754 651 | 1 | 00651 | Sat Feb 21 00:00:00 1970 PST
5755 653 | 303 | 00653_update3 | Mon Feb 23 00:00:00 1970 PST
5756 654 | 4 | 00654 | Tue Feb 24 00:00:00 1970 PST
5757 656 | 6 | 00656 | Thu Feb 26 00:00:00 1970 PST
5758 657 | 407 | 00657_update7 | Fri Feb 27 00:00:00 1970 PST
5759 658 | 8 | 00658 | Sat Feb 28 00:00:00 1970 PST
5760 659 | 509 | 00659_update9 | Sun Mar 01 00:00:00 1970 PST
5761 660 | 0 | 00660 | Mon Mar 02 00:00:00 1970 PST
5762 661 | 1 | 00661 | Tue Mar 03 00:00:00 1970 PST
5763 663 | 303 | 00663_update3 | Thu Mar 05 00:00:00 1970 PST
5764 664 | 4 | 00664 | Fri Mar 06 00:00:00 1970 PST
5765 666 | 6 | 00666 | Sun Mar 08 00:00:00 1970 PST
5766 667 | 407 | 00667_update7 | Mon Mar 09 00:00:00 1970 PST
5767 668 | 8 | 00668 | Tue Mar 10 00:00:00 1970 PST
5768 669 | 509 | 00669_update9 | Wed Mar 11 00:00:00 1970 PST
5769 670 | 0 | 00670 | Thu Mar 12 00:00:00 1970 PST
5770 671 | 1 | 00671 | Fri Mar 13 00:00:00 1970 PST
5771 673 | 303 | 00673_update3 | Sun Mar 15 00:00:00 1970 PST
5772 674 | 4 | 00674 | Mon Mar 16 00:00:00 1970 PST
5773 676 | 6 | 00676 | Wed Mar 18 00:00:00 1970 PST
5774 677 | 407 | 00677_update7 | Thu Mar 19 00:00:00 1970 PST
5775 678 | 8 | 00678 | Fri Mar 20 00:00:00 1970 PST
5776 679 | 509 | 00679_update9 | Sat Mar 21 00:00:00 1970 PST
5777 680 | 0 | 00680 | Sun Mar 22 00:00:00 1970 PST
5778 681 | 1 | 00681 | Mon Mar 23 00:00:00 1970 PST
5779 683 | 303 | 00683_update3 | Wed Mar 25 00:00:00 1970 PST
5780 684 | 4 | 00684 | Thu Mar 26 00:00:00 1970 PST
5781 686 | 6 | 00686 | Sat Mar 28 00:00:00 1970 PST
5782 687 | 407 | 00687_update7 | Sun Mar 29 00:00:00 1970 PST
5783 688 | 8 | 00688 | Mon Mar 30 00:00:00 1970 PST
5784 689 | 509 | 00689_update9 | Tue Mar 31 00:00:00 1970 PST
5785 690 | 0 | 00690 | Wed Apr 01 00:00:00 1970 PST
5786 691 | 1 | 00691 | Thu Apr 02 00:00:00 1970 PST
5787 693 | 303 | 00693_update3 | Sat Apr 04 00:00:00 1970 PST
5788 694 | 4 | 00694 | Sun Apr 05 00:00:00 1970 PST
5789 696 | 6 | 00696 | Tue Apr 07 00:00:00 1970 PST
5790 697 | 407 | 00697_update7 | Wed Apr 08 00:00:00 1970 PST
5791 698 | 8 | 00698 | Thu Apr 09 00:00:00 1970 PST
5792 699 | 509 | 00699_update9 | Fri Apr 10 00:00:00 1970 PST
5793 700 | 0 | 00700 | Thu Jan 01 00:00:00 1970 PST
5794 701 | 1 | 00701 | Fri Jan 02 00:00:00 1970 PST
5795 703 | 303 | 00703_update3 | Sun Jan 04 00:00:00 1970 PST
5796 704 | 4 | 00704 | Mon Jan 05 00:00:00 1970 PST
5797 706 | 6 | 00706 | Wed Jan 07 00:00:00 1970 PST
5798 707 | 407 | 00707_update7 | Thu Jan 08 00:00:00 1970 PST
5799 708 | 8 | 00708 | Fri Jan 09 00:00:00 1970 PST
5800 709 | 509 | 00709_update9 | Sat Jan 10 00:00:00 1970 PST
5801 710 | 0 | 00710 | Sun Jan 11 00:00:00 1970 PST
5802 711 | 1 | 00711 | Mon Jan 12 00:00:00 1970 PST
5803 713 | 303 | 00713_update3 | Wed Jan 14 00:00:00 1970 PST
5804 714 | 4 | 00714 | Thu Jan 15 00:00:00 1970 PST
5805 716 | 6 | 00716 | Sat Jan 17 00:00:00 1970 PST
5806 717 | 407 | 00717_update7 | Sun Jan 18 00:00:00 1970 PST
5807 718 | 8 | 00718 | Mon Jan 19 00:00:00 1970 PST
5808 719 | 509 | 00719_update9 | Tue Jan 20 00:00:00 1970 PST
5809 720 | 0 | 00720 | Wed Jan 21 00:00:00 1970 PST
5810 721 | 1 | 00721 | Thu Jan 22 00:00:00 1970 PST
5811 723 | 303 | 00723_update3 | Sat Jan 24 00:00:00 1970 PST
5812 724 | 4 | 00724 | Sun Jan 25 00:00:00 1970 PST
5813 726 | 6 | 00726 | Tue Jan 27 00:00:00 1970 PST
5814 727 | 407 | 00727_update7 | Wed Jan 28 00:00:00 1970 PST
5815 728 | 8 | 00728 | Thu Jan 29 00:00:00 1970 PST
5816 729 | 509 | 00729_update9 | Fri Jan 30 00:00:00 1970 PST
5817 730 | 0 | 00730 | Sat Jan 31 00:00:00 1970 PST
5818 731 | 1 | 00731 | Sun Feb 01 00:00:00 1970 PST
5819 733 | 303 | 00733_update3 | Tue Feb 03 00:00:00 1970 PST
5820 734 | 4 | 00734 | Wed Feb 04 00:00:00 1970 PST
5821 736 | 6 | 00736 | Fri Feb 06 00:00:00 1970 PST
5822 737 | 407 | 00737_update7 | Sat Feb 07 00:00:00 1970 PST
5823 738 | 8 | 00738 | Sun Feb 08 00:00:00 1970 PST
5824 739 | 509 | 00739_update9 | Mon Feb 09 00:00:00 1970 PST
5825 740 | 0 | 00740 | Tue Feb 10 00:00:00 1970 PST
5826 741 | 1 | 00741 | Wed Feb 11 00:00:00 1970 PST
5827 743 | 303 | 00743_update3 | Fri Feb 13 00:00:00 1970 PST
5828 744 | 4 | 00744 | Sat Feb 14 00:00:00 1970 PST
5829 746 | 6 | 00746 | Mon Feb 16 00:00:00 1970 PST
5830 747 | 407 | 00747_update7 | Tue Feb 17 00:00:00 1970 PST
5831 748 | 8 | 00748 | Wed Feb 18 00:00:00 1970 PST
5832 749 | 509 | 00749_update9 | Thu Feb 19 00:00:00 1970 PST
5833 750 | 0 | 00750 | Fri Feb 20 00:00:00 1970 PST
5834 751 | 1 | 00751 | Sat Feb 21 00:00:00 1970 PST
5835 753 | 303 | 00753_update3 | Mon Feb 23 00:00:00 1970 PST
5836 754 | 4 | 00754 | Tue Feb 24 00:00:00 1970 PST
5837 756 | 6 | 00756 | Thu Feb 26 00:00:00 1970 PST
5838 757 | 407 | 00757_update7 | Fri Feb 27 00:00:00 1970 PST
5839 758 | 8 | 00758 | Sat Feb 28 00:00:00 1970 PST
5840 759 | 509 | 00759_update9 | Sun Mar 01 00:00:00 1970 PST
5841 760 | 0 | 00760 | Mon Mar 02 00:00:00 1970 PST
5842 761 | 1 | 00761 | Tue Mar 03 00:00:00 1970 PST
5843 763 | 303 | 00763_update3 | Thu Mar 05 00:00:00 1970 PST
5844 764 | 4 | 00764 | Fri Mar 06 00:00:00 1970 PST
5845 766 | 6 | 00766 | Sun Mar 08 00:00:00 1970 PST
5846 767 | 407 | 00767_update7 | Mon Mar 09 00:00:00 1970 PST
5847 768 | 8 | 00768 | Tue Mar 10 00:00:00 1970 PST
5848 769 | 509 | 00769_update9 | Wed Mar 11 00:00:00 1970 PST
5849 770 | 0 | 00770 | Thu Mar 12 00:00:00 1970 PST
5850 771 | 1 | 00771 | Fri Mar 13 00:00:00 1970 PST
5851 773 | 303 | 00773_update3 | Sun Mar 15 00:00:00 1970 PST
5852 774 | 4 | 00774 | Mon Mar 16 00:00:00 1970 PST
5853 776 | 6 | 00776 | Wed Mar 18 00:00:00 1970 PST
5854 777 | 407 | 00777_update7 | Thu Mar 19 00:00:00 1970 PST
5855 778 | 8 | 00778 | Fri Mar 20 00:00:00 1970 PST
5856 779 | 509 | 00779_update9 | Sat Mar 21 00:00:00 1970 PST
5857 780 | 0 | 00780 | Sun Mar 22 00:00:00 1970 PST
5858 781 | 1 | 00781 | Mon Mar 23 00:00:00 1970 PST
5859 783 | 303 | 00783_update3 | Wed Mar 25 00:00:00 1970 PST
5860 784 | 4 | 00784 | Thu Mar 26 00:00:00 1970 PST
5861 786 | 6 | 00786 | Sat Mar 28 00:00:00 1970 PST
5862 787 | 407 | 00787_update7 | Sun Mar 29 00:00:00 1970 PST
5863 788 | 8 | 00788 | Mon Mar 30 00:00:00 1970 PST
5864 789 | 509 | 00789_update9 | Tue Mar 31 00:00:00 1970 PST
5865 790 | 0 | 00790 | Wed Apr 01 00:00:00 1970 PST
5866 791 | 1 | 00791 | Thu Apr 02 00:00:00 1970 PST
5867 793 | 303 | 00793_update3 | Sat Apr 04 00:00:00 1970 PST
5868 794 | 4 | 00794 | Sun Apr 05 00:00:00 1970 PST
5869 796 | 6 | 00796 | Tue Apr 07 00:00:00 1970 PST
5870 797 | 407 | 00797_update7 | Wed Apr 08 00:00:00 1970 PST
5871 798 | 8 | 00798 | Thu Apr 09 00:00:00 1970 PST
5872 799 | 509 | 00799_update9 | Fri Apr 10 00:00:00 1970 PST
5873 800 | 0 | 00800 | Thu Jan 01 00:00:00 1970 PST
5874 801 | 1 | 00801 | Fri Jan 02 00:00:00 1970 PST
5875 803 | 303 | 00803_update3 | Sun Jan 04 00:00:00 1970 PST
5876 804 | 4 | 00804 | Mon Jan 05 00:00:00 1970 PST
5877 806 | 6 | 00806 | Wed Jan 07 00:00:00 1970 PST
5878 807 | 407 | 00807_update7 | Thu Jan 08 00:00:00 1970 PST
5879 808 | 8 | 00808 | Fri Jan 09 00:00:00 1970 PST
5880 809 | 509 | 00809_update9 | Sat Jan 10 00:00:00 1970 PST
5881 810 | 0 | 00810 | Sun Jan 11 00:00:00 1970 PST
5882 811 | 1 | 00811 | Mon Jan 12 00:00:00 1970 PST
5883 813 | 303 | 00813_update3 | Wed Jan 14 00:00:00 1970 PST
5884 814 | 4 | 00814 | Thu Jan 15 00:00:00 1970 PST
5885 816 | 6 | 00816 | Sat Jan 17 00:00:00 1970 PST
5886 817 | 407 | 00817_update7 | Sun Jan 18 00:00:00 1970 PST
5887 818 | 8 | 00818 | Mon Jan 19 00:00:00 1970 PST
5888 819 | 509 | 00819_update9 | Tue Jan 20 00:00:00 1970 PST
5889 820 | 0 | 00820 | Wed Jan 21 00:00:00 1970 PST
5890 821 | 1 | 00821 | Thu Jan 22 00:00:00 1970 PST
5891 823 | 303 | 00823_update3 | Sat Jan 24 00:00:00 1970 PST
5892 824 | 4 | 00824 | Sun Jan 25 00:00:00 1970 PST
5893 826 | 6 | 00826 | Tue Jan 27 00:00:00 1970 PST
5894 827 | 407 | 00827_update7 | Wed Jan 28 00:00:00 1970 PST
5895 828 | 8 | 00828 | Thu Jan 29 00:00:00 1970 PST
5896 829 | 509 | 00829_update9 | Fri Jan 30 00:00:00 1970 PST
5897 830 | 0 | 00830 | Sat Jan 31 00:00:00 1970 PST
5898 831 | 1 | 00831 | Sun Feb 01 00:00:00 1970 PST
5899 833 | 303 | 00833_update3 | Tue Feb 03 00:00:00 1970 PST
5900 834 | 4 | 00834 | Wed Feb 04 00:00:00 1970 PST
5901 836 | 6 | 00836 | Fri Feb 06 00:00:00 1970 PST
5902 837 | 407 | 00837_update7 | Sat Feb 07 00:00:00 1970 PST
5903 838 | 8 | 00838 | Sun Feb 08 00:00:00 1970 PST
5904 839 | 509 | 00839_update9 | Mon Feb 09 00:00:00 1970 PST
5905 840 | 0 | 00840 | Tue Feb 10 00:00:00 1970 PST
5906 841 | 1 | 00841 | Wed Feb 11 00:00:00 1970 PST
5907 843 | 303 | 00843_update3 | Fri Feb 13 00:00:00 1970 PST
5908 844 | 4 | 00844 | Sat Feb 14 00:00:00 1970 PST
5909 846 | 6 | 00846 | Mon Feb 16 00:00:00 1970 PST
5910 847 | 407 | 00847_update7 | Tue Feb 17 00:00:00 1970 PST
5911 848 | 8 | 00848 | Wed Feb 18 00:00:00 1970 PST
5912 849 | 509 | 00849_update9 | Thu Feb 19 00:00:00 1970 PST
5913 850 | 0 | 00850 | Fri Feb 20 00:00:00 1970 PST
5914 851 | 1 | 00851 | Sat Feb 21 00:00:00 1970 PST
5915 853 | 303 | 00853_update3 | Mon Feb 23 00:00:00 1970 PST
5916 854 | 4 | 00854 | Tue Feb 24 00:00:00 1970 PST
5917 856 | 6 | 00856 | Thu Feb 26 00:00:00 1970 PST
5918 857 | 407 | 00857_update7 | Fri Feb 27 00:00:00 1970 PST
5919 858 | 8 | 00858 | Sat Feb 28 00:00:00 1970 PST
5920 859 | 509 | 00859_update9 | Sun Mar 01 00:00:00 1970 PST
5921 860 | 0 | 00860 | Mon Mar 02 00:00:00 1970 PST
5922 861 | 1 | 00861 | Tue Mar 03 00:00:00 1970 PST
5923 863 | 303 | 00863_update3 | Thu Mar 05 00:00:00 1970 PST
5924 864 | 4 | 00864 | Fri Mar 06 00:00:00 1970 PST
5925 866 | 6 | 00866 | Sun Mar 08 00:00:00 1970 PST
5926 867 | 407 | 00867_update7 | Mon Mar 09 00:00:00 1970 PST
5927 868 | 8 | 00868 | Tue Mar 10 00:00:00 1970 PST
5928 869 | 509 | 00869_update9 | Wed Mar 11 00:00:00 1970 PST
5929 870 | 0 | 00870 | Thu Mar 12 00:00:00 1970 PST
5930 871 | 1 | 00871 | Fri Mar 13 00:00:00 1970 PST
5931 873 | 303 | 00873_update3 | Sun Mar 15 00:00:00 1970 PST
5932 874 | 4 | 00874 | Mon Mar 16 00:00:00 1970 PST
5933 876 | 6 | 00876 | Wed Mar 18 00:00:00 1970 PST
5934 877 | 407 | 00877_update7 | Thu Mar 19 00:00:00 1970 PST
5935 878 | 8 | 00878 | Fri Mar 20 00:00:00 1970 PST
5936 879 | 509 | 00879_update9 | Sat Mar 21 00:00:00 1970 PST
5937 880 | 0 | 00880 | Sun Mar 22 00:00:00 1970 PST
5938 881 | 1 | 00881 | Mon Mar 23 00:00:00 1970 PST
5939 883 | 303 | 00883_update3 | Wed Mar 25 00:00:00 1970 PST
5940 884 | 4 | 00884 | Thu Mar 26 00:00:00 1970 PST
5941 886 | 6 | 00886 | Sat Mar 28 00:00:00 1970 PST
5942 887 | 407 | 00887_update7 | Sun Mar 29 00:00:00 1970 PST
5943 888 | 8 | 00888 | Mon Mar 30 00:00:00 1970 PST
5944 889 | 509 | 00889_update9 | Tue Mar 31 00:00:00 1970 PST
5945 890 | 0 | 00890 | Wed Apr 01 00:00:00 1970 PST
5946 891 | 1 | 00891 | Thu Apr 02 00:00:00 1970 PST
5947 893 | 303 | 00893_update3 | Sat Apr 04 00:00:00 1970 PST
5948 894 | 4 | 00894 | Sun Apr 05 00:00:00 1970 PST
5949 896 | 6 | 00896 | Tue Apr 07 00:00:00 1970 PST
5950 897 | 407 | 00897_update7 | Wed Apr 08 00:00:00 1970 PST
5951 898 | 8 | 00898 | Thu Apr 09 00:00:00 1970 PST
5952 899 | 509 | 00899_update9 | Fri Apr 10 00:00:00 1970 PST
5953 900 | 0 | 00900 | Thu Jan 01 00:00:00 1970 PST
5954 901 | 1 | 00901 | Fri Jan 02 00:00:00 1970 PST
5955 903 | 303 | 00903_update3 | Sun Jan 04 00:00:00 1970 PST
5956 904 | 4 | 00904 | Mon Jan 05 00:00:00 1970 PST
5957 906 | 6 | 00906 | Wed Jan 07 00:00:00 1970 PST
5958 907 | 407 | 00907_update7 | Thu Jan 08 00:00:00 1970 PST
5959 908 | 8 | 00908 | Fri Jan 09 00:00:00 1970 PST
5960 909 | 509 | 00909_update9 | Sat Jan 10 00:00:00 1970 PST
5961 910 | 0 | 00910 | Sun Jan 11 00:00:00 1970 PST
5962 911 | 1 | 00911 | Mon Jan 12 00:00:00 1970 PST
5963 913 | 303 | 00913_update3 | Wed Jan 14 00:00:00 1970 PST
5964 914 | 4 | 00914 | Thu Jan 15 00:00:00 1970 PST
5965 916 | 6 | 00916 | Sat Jan 17 00:00:00 1970 PST
5966 917 | 407 | 00917_update7 | Sun Jan 18 00:00:00 1970 PST
5967 918 | 8 | 00918 | Mon Jan 19 00:00:00 1970 PST
5968 919 | 509 | 00919_update9 | Tue Jan 20 00:00:00 1970 PST
5969 920 | 0 | 00920 | Wed Jan 21 00:00:00 1970 PST
5970 921 | 1 | 00921 | Thu Jan 22 00:00:00 1970 PST
5971 923 | 303 | 00923_update3 | Sat Jan 24 00:00:00 1970 PST
5972 924 | 4 | 00924 | Sun Jan 25 00:00:00 1970 PST
5973 926 | 6 | 00926 | Tue Jan 27 00:00:00 1970 PST
5974 927 | 407 | 00927_update7 | Wed Jan 28 00:00:00 1970 PST
5975 928 | 8 | 00928 | Thu Jan 29 00:00:00 1970 PST
5976 929 | 509 | 00929_update9 | Fri Jan 30 00:00:00 1970 PST
5977 930 | 0 | 00930 | Sat Jan 31 00:00:00 1970 PST
5978 931 | 1 | 00931 | Sun Feb 01 00:00:00 1970 PST
5979 933 | 303 | 00933_update3 | Tue Feb 03 00:00:00 1970 PST
5980 934 | 4 | 00934 | Wed Feb 04 00:00:00 1970 PST
5981 936 | 6 | 00936 | Fri Feb 06 00:00:00 1970 PST
5982 937 | 407 | 00937_update7 | Sat Feb 07 00:00:00 1970 PST
5983 938 | 8 | 00938 | Sun Feb 08 00:00:00 1970 PST
5984 939 | 509 | 00939_update9 | Mon Feb 09 00:00:00 1970 PST
5985 940 | 0 | 00940 | Tue Feb 10 00:00:00 1970 PST
5986 941 | 1 | 00941 | Wed Feb 11 00:00:00 1970 PST
5987 943 | 303 | 00943_update3 | Fri Feb 13 00:00:00 1970 PST
5988 944 | 4 | 00944 | Sat Feb 14 00:00:00 1970 PST
5989 946 | 6 | 00946 | Mon Feb 16 00:00:00 1970 PST
5990 947 | 407 | 00947_update7 | Tue Feb 17 00:00:00 1970 PST
5991 948 | 8 | 00948 | Wed Feb 18 00:00:00 1970 PST
5992 949 | 509 | 00949_update9 | Thu Feb 19 00:00:00 1970 PST
5993 950 | 0 | 00950 | Fri Feb 20 00:00:00 1970 PST
5994 951 | 1 | 00951 | Sat Feb 21 00:00:00 1970 PST
5995 953 | 303 | 00953_update3 | Mon Feb 23 00:00:00 1970 PST
5996 954 | 4 | 00954 | Tue Feb 24 00:00:00 1970 PST
5997 956 | 6 | 00956 | Thu Feb 26 00:00:00 1970 PST
5998 957 | 407 | 00957_update7 | Fri Feb 27 00:00:00 1970 PST
5999 958 | 8 | 00958 | Sat Feb 28 00:00:00 1970 PST
6000 959 | 509 | 00959_update9 | Sun Mar 01 00:00:00 1970 PST
6001 960 | 0 | 00960 | Mon Mar 02 00:00:00 1970 PST
6002 961 | 1 | 00961 | Tue Mar 03 00:00:00 1970 PST
6003 963 | 303 | 00963_update3 | Thu Mar 05 00:00:00 1970 PST
6004 964 | 4 | 00964 | Fri Mar 06 00:00:00 1970 PST
6005 966 | 6 | 00966 | Sun Mar 08 00:00:00 1970 PST
6006 967 | 407 | 00967_update7 | Mon Mar 09 00:00:00 1970 PST
6007 968 | 8 | 00968 | Tue Mar 10 00:00:00 1970 PST
6008 969 | 509 | 00969_update9 | Wed Mar 11 00:00:00 1970 PST
6009 970 | 0 | 00970 | Thu Mar 12 00:00:00 1970 PST
6010 971 | 1 | 00971 | Fri Mar 13 00:00:00 1970 PST
6011 973 | 303 | 00973_update3 | Sun Mar 15 00:00:00 1970 PST
6012 974 | 4 | 00974 | Mon Mar 16 00:00:00 1970 PST
6013 976 | 6 | 00976 | Wed Mar 18 00:00:00 1970 PST
6014 977 | 407 | 00977_update7 | Thu Mar 19 00:00:00 1970 PST
6015 978 | 8 | 00978 | Fri Mar 20 00:00:00 1970 PST
6016 979 | 509 | 00979_update9 | Sat Mar 21 00:00:00 1970 PST
6017 980 | 0 | 00980 | Sun Mar 22 00:00:00 1970 PST
6018 981 | 1 | 00981 | Mon Mar 23 00:00:00 1970 PST
6019 983 | 303 | 00983_update3 | Wed Mar 25 00:00:00 1970 PST
6020 984 | 4 | 00984 | Thu Mar 26 00:00:00 1970 PST
6021 986 | 6 | 00986 | Sat Mar 28 00:00:00 1970 PST
6022 987 | 407 | 00987_update7 | Sun Mar 29 00:00:00 1970 PST
6023 988 | 8 | 00988 | Mon Mar 30 00:00:00 1970 PST
6024 989 | 509 | 00989_update9 | Tue Mar 31 00:00:00 1970 PST
6025 990 | 0 | 00990 | Wed Apr 01 00:00:00 1970 PST
6026 991 | 1 | 00991 | Thu Apr 02 00:00:00 1970 PST
6027 993 | 303 | 00993_update3 | Sat Apr 04 00:00:00 1970 PST
6028 994 | 4 | 00994 | Sun Apr 05 00:00:00 1970 PST
6029 996 | 6 | 00996 | Tue Apr 07 00:00:00 1970 PST
6030 997 | 407 | 00997_update7 | Wed Apr 08 00:00:00 1970 PST
6031 998 | 8 | 00998 | Thu Apr 09 00:00:00 1970 PST
6032 999 | 509 | 00999_update9 | Fri Apr 10 00:00:00 1970 PST
6033 1000 | 0 | 01000 | Thu Jan 01 00:00:00 1970 PST
6034 1001 | 101 | 0000100001 |
6035 1003 | 403 | 0000300003_update3 |
6036 1004 | 104 | 0000400004 |
6037 1006 | 106 | 0000600006 |
6038 1007 | 507 | 0000700007_update7 |
6039 1008 | 108 | 0000800008 |
6040 1009 | 609 | 0000900009_update9 |
6041 1010 | 100 | 0001000010 |
6042 1011 | 101 | 0001100011 |
6043 1013 | 403 | 0001300013_update3 |
6044 1014 | 104 | 0001400014 |
6045 1016 | 106 | 0001600016 |
6046 1017 | 507 | 0001700017_update7 |
6047 1018 | 108 | 0001800018 |
6048 1019 | 609 | 0001900019_update9 |
6049 1020 | 100 | 0002000020 |
6051 1103 | 503 | ccc_update3 |
6055 EXPLAIN (verbose, costs off)
6056 INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo') RETURNING tableoid::regclass;
6058 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6059 Insert on public.ft2
6060 Output: (ft2.tableoid)::regclass
6061 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)
6064 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
6067 INSERT INTO ft2 (c1,c2,c3) VALUES (1200,999,'foo') RETURNING tableoid::regclass;
6073 EXPLAIN (verbose, costs off)
6074 UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200 RETURNING tableoid::regclass; -- can be pushed down
6076 ------------------------------------------------------------------------------------
6077 Update on public.ft2
6078 Output: (tableoid)::regclass
6079 -> Foreign Update on public.ft2
6080 Remote SQL: UPDATE "S 1"."T 1" SET c3 = 'bar'::text WHERE (("C 1" = 1200))
6083 UPDATE ft2 SET c3 = 'bar' WHERE c1 = 1200 RETURNING tableoid::regclass;
6089 EXPLAIN (verbose, costs off)
6090 DELETE FROM ft2 WHERE c1 = 1200 RETURNING tableoid::regclass; -- can be pushed down
6092 --------------------------------------------------------------------
6093 Delete on public.ft2
6094 Output: (tableoid)::regclass
6095 -> Foreign Delete on public.ft2
6096 Remote SQL: DELETE FROM "S 1"."T 1" WHERE (("C 1" = 1200))
6099 DELETE FROM ft2 WHERE c1 = 1200 RETURNING tableoid::regclass;
6105 -- Test UPDATE/DELETE with RETURNING on a three-table join
6106 INSERT INTO ft2 (c1,c2,c3)
6107 SELECT id, id - 1200, to_char(id, 'FM00000') FROM generate_series(1201, 1300) id;
6108 EXPLAIN (verbose, costs off)
6109 UPDATE ft2 SET c3 = 'foo'
6110 FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
6111 WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
6112 RETURNING ft2, ft2.*, ft4, ft4.*; -- can be pushed down
6114 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6115 Update on public.ft2
6116 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
6118 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
6121 UPDATE ft2 SET c3 = 'foo'
6122 FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
6123 WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
6124 RETURNING ft2, ft2.*, ft4, ft4.*;
6125 ft2 | c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | ft4 | c1 | c2 | c3
6126 --------------------------------+------+----+-----+----+----+----+------------+----+----------------+----+----+--------
6127 (1206,6,foo,,,,"ft2 ",) | 1206 | 6 | foo | | | | ft2 | | (6,7,AAA006) | 6 | 7 | AAA006
6128 (1212,12,foo,,,,"ft2 ",) | 1212 | 12 | foo | | | | ft2 | | (12,13,AAA012) | 12 | 13 | AAA012
6129 (1218,18,foo,,,,"ft2 ",) | 1218 | 18 | foo | | | | ft2 | | (18,19,AAA018) | 18 | 19 | AAA018
6130 (1224,24,foo,,,,"ft2 ",) | 1224 | 24 | foo | | | | ft2 | | (24,25,AAA024) | 24 | 25 | AAA024
6131 (1230,30,foo,,,,"ft2 ",) | 1230 | 30 | foo | | | | ft2 | | (30,31,AAA030) | 30 | 31 | AAA030
6132 (1236,36,foo,,,,"ft2 ",) | 1236 | 36 | foo | | | | ft2 | | (36,37,AAA036) | 36 | 37 | AAA036
6133 (1242,42,foo,,,,"ft2 ",) | 1242 | 42 | foo | | | | ft2 | | (42,43,AAA042) | 42 | 43 | AAA042
6134 (1248,48,foo,,,,"ft2 ",) | 1248 | 48 | foo | | | | ft2 | | (48,49,AAA048) | 48 | 49 | AAA048
6135 (1254,54,foo,,,,"ft2 ",) | 1254 | 54 | foo | | | | ft2 | | (54,55,AAA054) | 54 | 55 | AAA054
6136 (1260,60,foo,,,,"ft2 ",) | 1260 | 60 | foo | | | | ft2 | | (60,61,AAA060) | 60 | 61 | AAA060
6137 (1266,66,foo,,,,"ft2 ",) | 1266 | 66 | foo | | | | ft2 | | (66,67,AAA066) | 66 | 67 | AAA066
6138 (1272,72,foo,,,,"ft2 ",) | 1272 | 72 | foo | | | | ft2 | | (72,73,AAA072) | 72 | 73 | AAA072
6139 (1278,78,foo,,,,"ft2 ",) | 1278 | 78 | foo | | | | ft2 | | (78,79,AAA078) | 78 | 79 | AAA078
6140 (1284,84,foo,,,,"ft2 ",) | 1284 | 84 | foo | | | | ft2 | | (84,85,AAA084) | 84 | 85 | AAA084
6141 (1290,90,foo,,,,"ft2 ",) | 1290 | 90 | foo | | | | ft2 | | (90,91,AAA090) | 90 | 91 | AAA090
6142 (1296,96,foo,,,,"ft2 ",) | 1296 | 96 | foo | | | | ft2 | | (96,97,AAA096) | 96 | 97 | AAA096
6145 EXPLAIN (verbose, costs off)
6147 USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1)
6148 WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1
6149 RETURNING 100; -- can be pushed down
6151 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6152 Delete on public.ft2
6155 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))
6159 USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1)
6160 WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1
6176 DELETE FROM ft2 WHERE ft2.c1 > 1200;
6177 -- Test UPDATE with a MULTIEXPR sub-select
6178 -- (maybe someday this'll be remotely executable, but not today)
6179 EXPLAIN (verbose, costs off)
6180 UPDATE ft2 AS target SET (c2, c7) = (
6183 WHERE target.c1 = src.c1
6186 -----------------------------------------------------------------------------------------------------------------------
6187 Update on public.ft2 target
6188 Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c7 = $3 WHERE ctid = $1
6189 -> Foreign Scan on public.ft2 target
6190 Output: (SubPlan 1).col1, (SubPlan 1).col2, (rescan SubPlan 1), target.ctid, target.*
6191 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 1100)) FOR UPDATE
6193 -> Foreign Scan on public.ft2 src
6194 Output: (src.c2 * 10), src.c7
6195 Remote SQL: SELECT c2, c7 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
6198 UPDATE ft2 AS target SET (c2, c7) = (
6201 WHERE target.c1 = src.c1
6203 UPDATE ft2 AS target SET (c2) = (
6206 WHERE target.c1 = src.c1
6208 -- Test UPDATE involving a join that can be pushed down,
6209 -- but a SET clause that can't be
6210 EXPLAIN (VERBOSE, COSTS OFF)
6211 UPDATE ft2 d SET c2 = CASE WHEN random() >= 0 THEN d.c2 ELSE 0 END
6212 FROM ft2 AS t WHERE d.c1 = t.c1 AND d.c1 > 1000;
6214 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6215 Update on public.ft2 d
6216 Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2 WHERE ctid = $1
6218 Output: CASE WHEN (random() >= '0'::double precision) THEN d.c2 ELSE 0 END, d.ctid, d.*, t.*
6219 Relations: (public.ft2 d) INNER JOIN (public.ft2 t)
6220 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
6222 Output: d.c2, d.ctid, d.*, t.*
6223 Hash Cond: (d.c1 = t.c1)
6224 -> Foreign Scan on public.ft2 d
6225 Output: d.c2, d.ctid, d.*, d.c1
6226 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
6229 -> Foreign Scan on public.ft2 t
6231 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
6234 UPDATE ft2 d SET c2 = CASE WHEN random() >= 0 THEN d.c2 ELSE 0 END
6235 FROM ft2 AS t WHERE d.c1 = t.c1 AND d.c1 > 1000;
6236 -- Test UPDATE/DELETE with WHERE or JOIN/ON conditions containing
6237 -- user-defined operators/functions
6238 ALTER SERVER loopback OPTIONS (DROP extensions);
6239 INSERT INTO ft2 (c1,c2,c3)
6240 SELECT id, id % 10, to_char(id, 'FM00000') FROM generate_series(2001, 2010) id;
6241 EXPLAIN (verbose, costs off)
6242 UPDATE ft2 SET c3 = 'bar' WHERE postgres_fdw_abs(c1) > 2000 RETURNING *; -- can't be pushed down
6244 ----------------------------------------------------------------------------------------------------------
6245 Update on public.ft2
6246 Output: c1, c2, c3, c4, c5, c6, c7, c8
6247 Remote SQL: UPDATE "S 1"."T 1" SET c3 = $2 WHERE ctid = $1 RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8
6248 -> Foreign Scan on public.ft2
6249 Output: 'bar'::text, ctid, ft2.*
6250 Filter: (postgres_fdw_abs(ft2.c1) > 2000)
6251 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" FOR UPDATE
6254 UPDATE ft2 SET c3 = 'bar' WHERE postgres_fdw_abs(c1) > 2000 RETURNING *;
6255 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6256 ------+----+-----+----+----+----+------------+----
6257 2001 | 1 | bar | | | | ft2 |
6258 2002 | 2 | bar | | | | ft2 |
6259 2003 | 3 | bar | | | | ft2 |
6260 2004 | 4 | bar | | | | ft2 |
6261 2005 | 5 | bar | | | | ft2 |
6262 2006 | 6 | bar | | | | ft2 |
6263 2007 | 7 | bar | | | | ft2 |
6264 2008 | 8 | bar | | | | ft2 |
6265 2009 | 9 | bar | | | | ft2 |
6266 2010 | 0 | bar | | | | ft2 |
6269 EXPLAIN (verbose, costs off)
6270 UPDATE ft2 SET c3 = 'baz'
6271 FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
6272 WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1
6273 RETURNING ft2.*, ft4.*, ft5.*; -- can't be pushed down
6275 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6276 Update on public.ft2
6277 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
6278 Remote SQL: UPDATE "S 1"."T 1" SET c3 = $2 WHERE ctid = $1 RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8
6280 Output: 'baz'::text, ft2.ctid, ft2.*, ft4.*, ft5.*, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3
6281 Join Filter: (ft2.c2 === ft4.c1)
6282 -> Foreign Scan on public.ft2
6283 Output: ft2.ctid, ft2.*, ft2.c2
6284 Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 2000)) FOR UPDATE
6286 Output: ft4.*, ft4.c1, ft4.c2, ft4.c3, ft5.*, ft5.c1, ft5.c2, ft5.c3
6287 Relations: (public.ft4) INNER JOIN (public.ft5)
6288 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))))
6290 Output: ft4.*, ft4.c1, ft4.c2, ft4.c3, ft5.*, ft5.c1, ft5.c2, ft5.c3
6291 Hash Cond: (ft4.c1 = ft5.c1)
6292 -> Foreign Scan on public.ft4
6293 Output: ft4.*, ft4.c1, ft4.c2, ft4.c3
6294 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
6296 Output: ft5.*, ft5.c1, ft5.c2, ft5.c3
6297 -> Foreign Scan on public.ft5
6298 Output: ft5.*, ft5.c1, ft5.c2, ft5.c3
6299 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4"
6302 UPDATE ft2 SET c3 = 'baz'
6303 FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
6304 WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1
6305 RETURNING ft2.*, ft4.*, ft5.*;
6306 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 | c1 | c2 | c3 | c1 | c2 | c3
6307 ------+----+-----+----+----+----+------------+----+----+----+--------+----+----+--------
6308 2006 | 6 | baz | | | | ft2 | | 6 | 7 | AAA006 | 6 | 7 | AAA006
6311 EXPLAIN (verbose, costs off)
6313 USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1)
6314 WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1
6315 RETURNING ft2.c1, ft2.c2, ft2.c3; -- can't be pushed down
6317 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
6318 Delete on public.ft2
6319 Output: ft2.c1, ft2.c2, ft2.c3
6320 Remote SQL: DELETE FROM "S 1"."T 1" WHERE ctid = $1 RETURNING "C 1", c2, c3
6322 Output: ft2.ctid, ft4.*, ft5.*
6323 Filter: (ft4.c1 === ft5.c1)
6324 Relations: ((public.ft2) INNER JOIN (public.ft4)) INNER JOIN (public.ft5)
6325 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
6327 Output: ft2.ctid, ft4.*, ft5.*, ft4.c1, ft5.c1
6329 Output: ft2.ctid, ft4.*, ft4.c1
6330 Join Filter: (ft2.c2 = ft4.c1)
6331 -> Foreign Scan on public.ft2
6332 Output: ft2.ctid, ft2.c2
6333 Remote SQL: SELECT c2, ctid FROM "S 1"."T 1" WHERE (("C 1" > 2000)) FOR UPDATE
6334 -> Foreign Scan on public.ft4
6335 Output: ft4.*, ft4.c1
6336 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
6337 -> Foreign Scan on public.ft5
6338 Output: ft5.*, ft5.c1
6339 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4"
6343 USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1)
6344 WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1
6345 RETURNING ft2.c1, ft2.c2, ft2.c3;
6351 DELETE FROM ft2 WHERE ft2.c1 > 2000;
6352 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
6353 -- Test that trigger on remote table works as expected
6354 CREATE OR REPLACE FUNCTION "S 1".F_BRTRIG() RETURNS trigger AS $$
6356 NEW.c3 = NEW.c3 || '_trig_update';
6359 $$ LANGUAGE plpgsql;
6360 CREATE TRIGGER t1_br_insert BEFORE INSERT OR UPDATE
6361 ON "S 1"."T 1" FOR EACH ROW EXECUTE PROCEDURE "S 1".F_BRTRIG();
6362 INSERT INTO ft2 (c1,c2,c3) VALUES (1208, 818, 'fff') RETURNING *;
6363 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6364 ------+-----+-----------------+----+----+----+------------+----
6365 1208 | 818 | fff_trig_update | | | | ft2 |
6368 INSERT INTO ft2 (c1,c2,c3,c6) VALUES (1218, 818, 'ggg', '(--;') RETURNING *;
6369 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6370 ------+-----+-----------------+----+----+------+------------+----
6371 1218 | 818 | ggg_trig_update | | | (--; | ft2 |
6374 UPDATE ft2 SET c2 = c2 + 600 WHERE c1 % 10 = 8 AND c1 < 1200 RETURNING *;
6375 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6376 ------+-----+------------------------+------------------------------+--------------------------+----+------------+-----
6377 8 | 608 | 00008_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6378 18 | 608 | 00018_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6379 28 | 608 | 00028_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6380 38 | 608 | 00038_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6381 48 | 608 | 00048_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6382 58 | 608 | 00058_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6383 68 | 608 | 00068_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6384 78 | 608 | 00078_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6385 88 | 608 | 00088_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6386 98 | 608 | 00098_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6387 108 | 608 | 00108_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6388 118 | 608 | 00118_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6389 128 | 608 | 00128_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6390 138 | 608 | 00138_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6391 148 | 608 | 00148_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6392 158 | 608 | 00158_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6393 168 | 608 | 00168_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6394 178 | 608 | 00178_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6395 188 | 608 | 00188_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6396 198 | 608 | 00198_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6397 208 | 608 | 00208_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6398 218 | 608 | 00218_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6399 228 | 608 | 00228_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6400 238 | 608 | 00238_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6401 248 | 608 | 00248_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6402 258 | 608 | 00258_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6403 268 | 608 | 00268_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6404 278 | 608 | 00278_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6405 288 | 608 | 00288_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6406 298 | 608 | 00298_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6407 308 | 608 | 00308_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6408 318 | 608 | 00318_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6409 328 | 608 | 00328_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6410 338 | 608 | 00338_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6411 348 | 608 | 00348_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6412 358 | 608 | 00358_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6413 368 | 608 | 00368_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6414 378 | 608 | 00378_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6415 388 | 608 | 00388_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6416 398 | 608 | 00398_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6417 408 | 608 | 00408_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6418 418 | 608 | 00418_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6419 428 | 608 | 00428_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6420 438 | 608 | 00438_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6421 448 | 608 | 00448_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6422 458 | 608 | 00458_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6423 468 | 608 | 00468_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6424 478 | 608 | 00478_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6425 488 | 608 | 00488_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6426 498 | 608 | 00498_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6427 508 | 608 | 00508_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6428 518 | 608 | 00518_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6429 528 | 608 | 00528_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6430 538 | 608 | 00538_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6431 548 | 608 | 00548_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6432 558 | 608 | 00558_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6433 568 | 608 | 00568_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6434 578 | 608 | 00578_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6435 588 | 608 | 00588_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6436 598 | 608 | 00598_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6437 608 | 608 | 00608_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6438 618 | 608 | 00618_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6439 628 | 608 | 00628_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6440 638 | 608 | 00638_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6441 648 | 608 | 00648_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6442 658 | 608 | 00658_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6443 668 | 608 | 00668_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6444 678 | 608 | 00678_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6445 688 | 608 | 00688_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6446 698 | 608 | 00698_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6447 708 | 608 | 00708_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6448 718 | 608 | 00718_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6449 728 | 608 | 00728_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6450 738 | 608 | 00738_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6451 748 | 608 | 00748_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6452 758 | 608 | 00758_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6453 768 | 608 | 00768_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6454 778 | 608 | 00778_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6455 788 | 608 | 00788_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6456 798 | 608 | 00798_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6457 808 | 608 | 00808_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6458 818 | 608 | 00818_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6459 828 | 608 | 00828_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6460 838 | 608 | 00838_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6461 848 | 608 | 00848_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6462 858 | 608 | 00858_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6463 868 | 608 | 00868_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6464 878 | 608 | 00878_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6465 888 | 608 | 00888_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6466 898 | 608 | 00898_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6467 908 | 608 | 00908_trig_update | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8 | 8 | foo
6468 918 | 608 | 00918_trig_update | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8 | 8 | foo
6469 928 | 608 | 00928_trig_update | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8 | 8 | foo
6470 938 | 608 | 00938_trig_update | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8 | 8 | foo
6471 948 | 608 | 00948_trig_update | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8 | 8 | foo
6472 958 | 608 | 00958_trig_update | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8 | 8 | foo
6473 968 | 608 | 00968_trig_update | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8 | 8 | foo
6474 978 | 608 | 00978_trig_update | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8 | 8 | foo
6475 988 | 608 | 00988_trig_update | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8 | 8 | foo
6476 998 | 608 | 00998_trig_update | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8 | 8 | foo
6477 1008 | 708 | 0000800008_trig_update | | | | ft2 |
6478 1018 | 708 | 0001800018_trig_update | | | | ft2 |
6481 -- Test errors thrown on remote side during update
6482 ALTER TABLE "S 1"."T 1" ADD CONSTRAINT c2positive CHECK (c2 >= 0);
6483 INSERT INTO ft1(c1, c2) VALUES(11, 12); -- duplicate key
6484 ERROR: duplicate key value violates unique constraint "t1_pkey"
6485 DETAIL: Key ("C 1")=(11) already exists.
6486 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)
6487 INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT DO NOTHING; -- works
6488 INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO NOTHING; -- unsupported
6489 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
6490 INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO UPDATE SET c3 = 'ffg'; -- unsupported
6491 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
6492 INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive
6493 ERROR: new row for relation "T 1" violates check constraint "c2positive"
6494 DETAIL: Failing row contains (1111, -2, null, null, null, null, ft1 , null).
6495 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)
6496 UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive
6497 ERROR: new row for relation "T 1" violates check constraint "c2positive"
6498 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).
6499 CONTEXT: remote SQL command: UPDATE "S 1"."T 1" SET c2 = (- c2) WHERE (("C 1" = 1))
6500 -- Test savepoint/rollback behavior
6501 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6519 select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
6538 update ft2 set c2 = 42 where c2 = 0;
6539 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6558 update ft2 set c2 = 44 where c2 = 4;
6559 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6577 release savepoint s1;
6578 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6597 update ft2 set c2 = 46 where c2 = 6;
6598 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6616 rollback to savepoint s2;
6617 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6635 release savepoint s2;
6636 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6655 update ft2 set c2 = -2 where c2 = 42 and c1 = 10; -- fail on remote side
6656 ERROR: new row for relation "T 1" violates check constraint "c2positive"
6657 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).
6658 CONTEXT: remote SQL command: UPDATE "S 1"."T 1" SET c2 = (-2) WHERE ((c2 = 42)) AND (("C 1" = 10))
6659 rollback to savepoint s3;
6660 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6678 release savepoint s3;
6679 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6697 -- none of the above is committed yet remotely
6698 select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
6717 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
6735 select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
6753 VACUUM ANALYZE "S 1"."T 1";
6754 -- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs
6755 -- FIRST behavior here.
6756 -- ORDER BY DESC NULLS LAST options
6757 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10;
6759 ---------------------------------------------------------------------------------------------------------------------------------------------------------------
6760 Foreign Scan on public.ft1
6761 Output: c1, c2, c3, c4, c5, c6, c7, c8
6762 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
6765 SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10;
6766 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6767 ------+-----+--------------------+------------------------------+--------------------------+------+------------+-----
6768 960 | 42 | 00960_trig_update | Mon Mar 02 00:00:00 1970 PST | Mon Mar 02 00:00:00 1970 | 0 | 0 | foo
6769 970 | 42 | 00970_trig_update | Thu Mar 12 00:00:00 1970 PST | Thu Mar 12 00:00:00 1970 | 0 | 0 | foo
6770 980 | 42 | 00980_trig_update | Sun Mar 22 00:00:00 1970 PST | Sun Mar 22 00:00:00 1970 | 0 | 0 | foo
6771 990 | 42 | 00990_trig_update | Wed Apr 01 00:00:00 1970 PST | Wed Apr 01 00:00:00 1970 | 0 | 0 | foo
6772 1000 | 42 | 01000_trig_update | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0 | 0 | foo
6773 1218 | 818 | ggg_trig_update | | | (--; | ft2 |
6774 1001 | 101 | 0000100001 | | | | ft2 |
6775 1003 | 403 | 0000300003_update3 | | | | ft2 |
6776 1004 | 104 | 0000400004 | | | | ft2 |
6777 1006 | 106 | 0000600006 | | | | ft2 |
6780 -- ORDER BY DESC NULLS FIRST options
6781 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 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 FIRST, "C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 15::bigint
6789 SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
6790 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
6791 ------+-----+-----------------+------------------------------+--------------------------+----+------------+-----
6792 1020 | 100 | 0002000020 | | | | ft2 |
6793 1101 | 201 | aaa | | | | ft2 |
6794 1103 | 503 | ccc_update3 | | | | ft2 |
6795 1104 | 204 | ddd | | | | ft2 |
6796 1208 | 818 | fff_trig_update | | | | ft2 |
6797 9 | 509 | 00009_update9 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9 | ft2 | foo
6798 19 | 509 | 00019_update9 | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9 | ft2 | foo
6799 29 | 509 | 00029_update9 | Fri Jan 30 00:00:00 1970 PST | Fri Jan 30 00:00:00 1970 | 9 | ft2 | foo
6800 39 | 509 | 00039_update9 | Mon Feb 09 00:00:00 1970 PST | Mon Feb 09 00:00:00 1970 | 9 | ft2 | foo
6801 49 | 509 | 00049_update9 | Thu Feb 19 00:00:00 1970 PST | Thu Feb 19 00:00:00 1970 | 9 | ft2 | foo
6804 -- ORDER BY ASC NULLS FIRST options
6805 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 ASC 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 ASC NULLS FIRST, "C 1" ASC NULLS LAST LIMIT 10::bigint OFFSET 15::bigint
6813 SELECT * FROM ft1 ORDER BY c6 ASC 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 1218 | 818 | ggg_trig_update | | | (--; | ft2 |
6822 10 | 42 | 00010_trig_update | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0 | 0 | foo
6823 20 | 42 | 00020_trig_update | Wed Jan 21 00:00:00 1970 PST | Wed Jan 21 00:00:00 1970 | 0 | 0 | foo
6824 30 | 42 | 00030_trig_update | Sat Jan 31 00:00:00 1970 PST | Sat Jan 31 00:00:00 1970 | 0 | 0 | foo
6825 40 | 42 | 00040_trig_update | Tue Feb 10 00:00:00 1970 PST | Tue Feb 10 00:00:00 1970 | 0 | 0 | foo
6828 -- ===================================================================
6829 -- test check constraints
6830 -- ===================================================================
6831 -- Consistent check constraints provide consistent results
6832 ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK (c2 >= 0);
6833 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0;
6835 -----------------------------------------------------------------
6838 Relations: Aggregate on (public.ft1)
6839 Remote SQL: SELECT count(*) FROM "S 1"."T 1" WHERE ((c2 < 0))
6842 SELECT count(*) FROM ft1 WHERE c2 < 0;
6848 SET constraint_exclusion = 'on';
6849 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0;
6851 --------------------------------
6855 One-Time Filter: false
6858 SELECT count(*) FROM ft1 WHERE c2 < 0;
6864 RESET constraint_exclusion;
6865 -- check constraint is enforced on the remote side, not locally
6866 INSERT INTO ft1(c1, c2) VALUES(1111, -2); -- c2positive
6867 ERROR: new row for relation "T 1" violates check constraint "c2positive"
6868 DETAIL: Failing row contains (1111, -2, null, null, null, null, ft1 , null).
6869 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)
6870 UPDATE ft1 SET c2 = -c2 WHERE c1 = 1; -- c2positive
6871 ERROR: new row for relation "T 1" violates check constraint "c2positive"
6872 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).
6873 CONTEXT: remote SQL command: UPDATE "S 1"."T 1" SET c2 = (- c2) WHERE (("C 1" = 1))
6874 ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive;
6875 -- But inconsistent check constraints provide inconsistent results
6876 ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK (c2 < 0);
6877 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0;
6879 ------------------------------------------------------------------
6882 Relations: Aggregate on (public.ft1)
6883 Remote SQL: SELECT count(*) FROM "S 1"."T 1" WHERE ((c2 >= 0))
6886 SELECT count(*) FROM ft1 WHERE c2 >= 0;
6892 SET constraint_exclusion = 'on';
6893 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0;
6895 --------------------------------
6899 One-Time Filter: false
6902 SELECT count(*) FROM ft1 WHERE c2 >= 0;
6908 RESET constraint_exclusion;
6909 -- local check constraint is not actually enforced
6910 INSERT INTO ft1(c1, c2) VALUES(1111, 2);
6911 UPDATE ft1 SET c2 = c2 + 1 WHERE c1 = 1;
6912 ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2negative;
6913 -- ===================================================================
6914 -- test WITH CHECK OPTION constraints
6915 -- ===================================================================
6916 CREATE FUNCTION row_before_insupd_trigfunc() RETURNS trigger AS $$BEGIN NEW.a := NEW.a + 10; RETURN NEW; END$$ LANGUAGE plpgsql;
6917 CREATE TABLE base_tbl (a int, b int);
6918 ALTER TABLE base_tbl SET (autovacuum_enabled = 'false');
6919 CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON base_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc();
6920 CREATE FOREIGN TABLE foreign_tbl (a int, b int)
6921 SERVER loopback OPTIONS (table_name 'base_tbl');
6922 CREATE VIEW rw_view AS SELECT * FROM foreign_tbl
6923 WHERE a < b WITH CHECK OPTION;
6925 View "public.rw_view"
6926 Column | Type | Collation | Nullable | Default | Storage | Description
6927 --------+---------+-----------+----------+---------+---------+-------------
6928 a | integer | | | | plain |
6929 b | integer | | | | plain |
6935 Options: check_option=cascaded
6937 EXPLAIN (VERBOSE, COSTS OFF)
6938 INSERT INTO rw_view VALUES (0, 5);
6940 --------------------------------------------------------------------------------
6941 Insert on public.foreign_tbl
6942 Remote SQL: INSERT INTO public.base_tbl(a, b) VALUES ($1, $2) RETURNING a, b
6948 INSERT INTO rw_view VALUES (0, 5); -- should fail
6949 ERROR: new row violates check option for view "rw_view"
6950 DETAIL: Failing row contains (10, 5).
6951 EXPLAIN (VERBOSE, COSTS OFF)
6952 INSERT INTO rw_view VALUES (0, 15);
6954 --------------------------------------------------------------------------------
6955 Insert on public.foreign_tbl
6956 Remote SQL: INSERT INTO public.base_tbl(a, b) VALUES ($1, $2) RETURNING a, b
6962 INSERT INTO rw_view VALUES (0, 15); -- ok
6963 SELECT * FROM foreign_tbl;
6969 EXPLAIN (VERBOSE, COSTS OFF)
6970 UPDATE rw_view SET b = b + 5;
6972 ---------------------------------------------------------------------------------------
6973 Update on public.foreign_tbl
6974 Remote SQL: UPDATE public.base_tbl SET b = $2 WHERE ctid = $1 RETURNING a, b
6975 -> Foreign Scan on public.foreign_tbl
6976 Output: (foreign_tbl.b + 5), foreign_tbl.ctid, foreign_tbl.*
6977 Remote SQL: SELECT a, b, ctid FROM public.base_tbl WHERE ((a < b)) FOR UPDATE
6980 UPDATE rw_view SET b = b + 5; -- should fail
6981 ERROR: new row violates check option for view "rw_view"
6982 DETAIL: Failing row contains (20, 20).
6983 EXPLAIN (VERBOSE, COSTS OFF)
6984 UPDATE rw_view SET b = b + 15;
6986 ---------------------------------------------------------------------------------------
6987 Update on public.foreign_tbl
6988 Remote SQL: UPDATE public.base_tbl SET b = $2 WHERE ctid = $1 RETURNING a, b
6989 -> Foreign Scan on public.foreign_tbl
6990 Output: (foreign_tbl.b + 15), foreign_tbl.ctid, foreign_tbl.*
6991 Remote SQL: SELECT a, b, ctid FROM public.base_tbl WHERE ((a < b)) FOR UPDATE
6994 UPDATE rw_view SET b = b + 15; -- ok
6995 SELECT * FROM foreign_tbl;
7001 -- We don't allow batch insert when there are any WCO constraints
7002 ALTER SERVER loopback OPTIONS (ADD batch_size '10');
7003 EXPLAIN (VERBOSE, COSTS OFF)
7004 INSERT INTO rw_view VALUES (0, 15), (0, 5);
7006 --------------------------------------------------------------------------------
7007 Insert on public.foreign_tbl
7008 Remote SQL: INSERT INTO public.base_tbl(a, b) VALUES ($1, $2) RETURNING a, b
7010 -> Values Scan on "*VALUES*"
7011 Output: "*VALUES*".column1, "*VALUES*".column2
7014 INSERT INTO rw_view VALUES (0, 15), (0, 5); -- should fail
7015 ERROR: new row violates check option for view "rw_view"
7016 DETAIL: Failing row contains (10, 5).
7017 SELECT * FROM foreign_tbl;
7023 ALTER SERVER loopback OPTIONS (DROP batch_size);
7024 DROP FOREIGN TABLE foreign_tbl CASCADE;
7025 NOTICE: drop cascades to view rw_view
7026 DROP TRIGGER row_before_insupd_trigger ON base_tbl;
7027 DROP TABLE base_tbl;
7028 -- test WCO for partitions
7029 CREATE TABLE child_tbl (a int, b int);
7030 ALTER TABLE child_tbl SET (autovacuum_enabled = 'false');
7031 CREATE TRIGGER row_before_insupd_trigger BEFORE INSERT OR UPDATE ON child_tbl FOR EACH ROW EXECUTE PROCEDURE row_before_insupd_trigfunc();
7032 CREATE FOREIGN TABLE foreign_tbl (a int, b int)
7033 SERVER loopback OPTIONS (table_name 'child_tbl');
7034 CREATE TABLE parent_tbl (a int, b int) PARTITION BY RANGE(a);
7035 ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100);
7036 -- Detach and re-attach once, to stress the concurrent detach case.
7037 ALTER TABLE parent_tbl DETACH PARTITION foreign_tbl CONCURRENTLY;
7038 ALTER TABLE parent_tbl ATTACH PARTITION foreign_tbl FOR VALUES FROM (0) TO (100);
7039 CREATE VIEW rw_view AS SELECT * FROM parent_tbl
7040 WHERE a < b WITH CHECK OPTION;
7042 View "public.rw_view"
7043 Column | Type | Collation | Nullable | Default | Storage | Description
7044 --------+---------+-----------+----------+---------+---------+-------------
7045 a | integer | | | | plain |
7046 b | integer | | | | plain |
7052 Options: check_option=cascaded
7054 EXPLAIN (VERBOSE, COSTS OFF)
7055 INSERT INTO rw_view VALUES (0, 5);
7057 -----------------------------
7058 Insert on public.parent_tbl
7063 INSERT INTO rw_view VALUES (0, 5); -- should fail
7064 ERROR: new row violates check option for view "rw_view"
7065 DETAIL: Failing row contains (10, 5).
7066 EXPLAIN (VERBOSE, COSTS OFF)
7067 INSERT INTO rw_view VALUES (0, 15);
7069 -----------------------------
7070 Insert on public.parent_tbl
7075 INSERT INTO rw_view VALUES (0, 15); -- ok
7076 SELECT * FROM foreign_tbl;
7082 EXPLAIN (VERBOSE, COSTS OFF)
7083 UPDATE rw_view SET b = b + 5;
7085 ------------------------------------------------------------------------------------------------
7086 Update on public.parent_tbl
7087 Foreign Update on public.foreign_tbl parent_tbl_1
7088 Remote SQL: UPDATE public.child_tbl SET b = $2 WHERE ctid = $1 RETURNING a, b
7089 -> Foreign Scan on public.foreign_tbl parent_tbl_1
7090 Output: (parent_tbl_1.b + 5), parent_tbl_1.tableoid, parent_tbl_1.ctid, parent_tbl_1.*
7091 Remote SQL: SELECT a, b, ctid FROM public.child_tbl WHERE ((a < b)) FOR UPDATE
7094 UPDATE rw_view SET b = b + 5; -- should fail
7095 ERROR: new row violates check option for view "rw_view"
7096 DETAIL: Failing row contains (20, 20).
7097 EXPLAIN (VERBOSE, COSTS OFF)
7098 UPDATE rw_view SET b = b + 15;
7100 -------------------------------------------------------------------------------------------------
7101 Update on public.parent_tbl
7102 Foreign Update on public.foreign_tbl parent_tbl_1
7103 Remote SQL: UPDATE public.child_tbl SET b = $2 WHERE ctid = $1 RETURNING a, b
7104 -> Foreign Scan on public.foreign_tbl parent_tbl_1
7105 Output: (parent_tbl_1.b + 15), parent_tbl_1.tableoid, parent_tbl_1.ctid, parent_tbl_1.*
7106 Remote SQL: SELECT a, b, ctid FROM public.child_tbl WHERE ((a < b)) FOR UPDATE
7109 UPDATE rw_view SET b = b + 15; -- ok
7110 SELECT * FROM foreign_tbl;
7116 -- We don't allow batch insert when there are any WCO constraints
7117 ALTER SERVER loopback OPTIONS (ADD batch_size '10');
7118 EXPLAIN (VERBOSE, COSTS OFF)
7119 INSERT INTO rw_view VALUES (0, 15), (0, 5);
7121 --------------------------------------------------------
7122 Insert on public.parent_tbl
7123 -> Values Scan on "*VALUES*"
7124 Output: "*VALUES*".column1, "*VALUES*".column2
7127 INSERT INTO rw_view VALUES (0, 15), (0, 5); -- should fail
7128 ERROR: new row violates check option for view "rw_view"
7129 DETAIL: Failing row contains (10, 5).
7130 SELECT * FROM foreign_tbl;
7136 ALTER SERVER loopback OPTIONS (DROP batch_size);
7137 DROP FOREIGN TABLE foreign_tbl CASCADE;
7138 DROP TRIGGER row_before_insupd_trigger ON child_tbl;
7139 DROP TABLE parent_tbl CASCADE;
7140 NOTICE: drop cascades to view rw_view
7141 DROP FUNCTION row_before_insupd_trigfunc;
7142 -- Try a more complex permutation of WCO where there are multiple levels of
7143 -- partitioned tables with columns not all in the same order
7144 CREATE TABLE parent_tbl (a int, b text, c numeric) PARTITION BY RANGE(a);
7145 CREATE TABLE sub_parent (c numeric, a int, b text) PARTITION BY RANGE(a);
7146 ALTER TABLE parent_tbl ATTACH PARTITION sub_parent FOR VALUES FROM (1) TO (10);
7147 CREATE TABLE child_local (b text, c numeric, a int);
7148 CREATE FOREIGN TABLE child_foreign (b text, c numeric, a int)
7149 SERVER loopback OPTIONS (table_name 'child_local');
7150 ALTER TABLE sub_parent ATTACH PARTITION child_foreign FOR VALUES FROM (1) TO (10);
7151 CREATE VIEW rw_view AS SELECT * FROM parent_tbl WHERE a < 5 WITH CHECK OPTION;
7152 INSERT INTO parent_tbl (a) VALUES(1),(5);
7153 EXPLAIN (VERBOSE, COSTS OFF)
7154 UPDATE rw_view SET b = 'text', c = 123.456;
7156 -------------------------------------------------------------------------------------------------
7157 Update on public.parent_tbl
7158 Foreign Update on public.child_foreign parent_tbl_1
7159 Remote SQL: UPDATE public.child_local SET b = $2, c = $3 WHERE ctid = $1 RETURNING a
7160 -> Foreign Scan on public.child_foreign parent_tbl_1
7161 Output: 'text'::text, 123.456, parent_tbl_1.tableoid, parent_tbl_1.ctid, parent_tbl_1.*
7162 Remote SQL: SELECT b, c, a, ctid FROM public.child_local WHERE ((a < 5)) FOR UPDATE
7165 UPDATE rw_view SET b = 'text', c = 123.456;
7166 SELECT * FROM parent_tbl ORDER BY a;
7168 ---+------+---------
7174 DROP TABLE child_local;
7175 DROP FOREIGN TABLE child_foreign;
7176 DROP TABLE sub_parent;
7177 DROP TABLE parent_tbl;
7178 -- ===================================================================
7179 -- test serial columns (ie, sequence-based defaults)
7180 -- ===================================================================
7181 create table loc1 (f1 serial, f2 text);
7182 alter table loc1 set (autovacuum_enabled = 'false');
7183 create foreign table rem1 (f1 serial, f2 text)
7184 server loopback options(table_name 'loc1');
7185 select pg_catalog.setval('rem1_f1_seq', 10, false);
7191 insert into loc1(f2) values('hi');
7192 insert into rem1(f2) values('hi remote');
7193 insert into loc1(f2) values('bye');
7194 insert into rem1(f2) values('bye remote');
7213 -- ===================================================================
7214 -- test generated columns
7215 -- ===================================================================
7216 create table gloc1 (
7218 b int generated always as (a * 2) stored);
7219 alter table gloc1 set (autovacuum_enabled = 'false');
7220 create foreign table grem1 (
7222 b int generated always as (a * 2) stored)
7223 server loopback options(table_name 'gloc1');
7224 explain (verbose, costs off)
7225 insert into grem1 (a) values (1), (2);
7227 -------------------------------------------------------------------
7228 Insert on public.grem1
7229 Remote SQL: INSERT INTO public.gloc1(a, b) VALUES ($1, DEFAULT)
7231 -> Values Scan on "*VALUES*"
7232 Output: "*VALUES*".column1, NULL::integer
7235 insert into grem1 (a) values (1), (2);
7236 explain (verbose, costs off)
7237 update grem1 set a = 22 where a = 2;
7239 ------------------------------------------------------------------------------------
7240 Update on public.grem1
7241 Remote SQL: UPDATE public.gloc1 SET a = $2, b = DEFAULT WHERE ctid = $1
7242 -> Foreign Scan on public.grem1
7243 Output: 22, ctid, grem1.*
7244 Remote SQL: SELECT a, b, ctid FROM public.gloc1 WHERE ((a = 2)) FOR UPDATE
7247 update grem1 set a = 22 where a = 2;
7248 select * from gloc1;
7255 select * from grem1;
7264 copy grem1 from stdin;
7265 select * from gloc1;
7272 select * from grem1;
7280 -- test batch insert
7281 alter server loopback options (add batch_size '10');
7282 explain (verbose, costs off)
7283 insert into grem1 (a) values (1), (2);
7285 -------------------------------------------------------------------
7286 Insert on public.grem1
7287 Remote SQL: INSERT INTO public.gloc1(a, b) VALUES ($1, DEFAULT)
7289 -> Values Scan on "*VALUES*"
7290 Output: "*VALUES*".column1, NULL::integer
7293 insert into grem1 (a) values (1), (2);
7294 select * from gloc1;
7301 select * from grem1;
7309 -- batch insert with foreign partitions.
7310 -- This schema uses two partitions, one local and one remote with a modulo
7311 -- to loop across all of them in batches.
7312 create table tab_batch_local (id int, data text);
7313 insert into tab_batch_local select i, 'test'|| i from generate_series(1, 45) i;
7314 create table tab_batch_sharded (id int, data text) partition by hash(id);
7315 create table tab_batch_sharded_p0 partition of tab_batch_sharded
7316 for values with (modulus 2, remainder 0);
7317 create table tab_batch_sharded_p1_remote (id int, data text);
7318 create foreign table tab_batch_sharded_p1 partition of tab_batch_sharded
7319 for values with (modulus 2, remainder 1)
7320 server loopback options (table_name 'tab_batch_sharded_p1_remote');
7321 insert into tab_batch_sharded select * from tab_batch_local;
7322 select count(*) from tab_batch_sharded;
7328 drop table tab_batch_local;
7329 drop table tab_batch_sharded;
7330 drop table tab_batch_sharded_p1_remote;
7331 alter server loopback options (drop batch_size);
7332 -- ===================================================================
7333 -- test local triggers
7334 -- ===================================================================
7335 -- Trigger functions "borrowed" from triggers regress test.
7336 CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$
7338 RAISE NOTICE 'trigger_func(%) called: action = %, when = %, level = %',
7339 TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL;
7342 CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1
7343 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
7344 CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1
7345 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
7346 CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger
7347 LANGUAGE plpgsql AS $$
7355 relid := TG_relid::regclass;
7357 for i in 0 .. TG_nargs - 1 loop
7359 argstr := argstr || ', ';
7361 argstr := argstr || TG_argv[i];
7364 RAISE NOTICE '%(%) % % % ON %',
7365 tg_name, argstr, TG_when, TG_level, TG_OP, relid;
7366 oldnew := '{}'::text[];
7367 if TG_OP != 'INSERT' then
7368 oldnew := array_append(oldnew, format('OLD: %s', OLD));
7371 if TG_OP != 'DELETE' then
7372 oldnew := array_append(oldnew, format('NEW: %s', NEW));
7375 RAISE NOTICE '%', array_to_string(oldnew, ',');
7377 if TG_OP = 'DELETE' then
7384 -- Test basic functionality
7385 CREATE TRIGGER trig_row_before
7386 BEFORE INSERT OR UPDATE OR DELETE ON rem1
7387 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7388 CREATE TRIGGER trig_row_after
7389 AFTER INSERT OR UPDATE OR DELETE ON rem1
7390 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7392 NOTICE: trigger_func(<NULL>) called: action = DELETE, when = BEFORE, level = STATEMENT
7393 NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
7395 NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
7396 NOTICE: OLD: (10,"hi remote")
7397 NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
7398 NOTICE: OLD: (2,bye)
7399 NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
7400 NOTICE: OLD: (11,"bye remote")
7401 NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
7403 NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
7404 NOTICE: OLD: (10,"hi remote")
7405 NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
7406 NOTICE: OLD: (2,bye)
7407 NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
7408 NOTICE: OLD: (11,"bye remote")
7409 NOTICE: trigger_func(<NULL>) called: action = DELETE, when = AFTER, level = STATEMENT
7410 insert into rem1 values(1,'insert');
7411 NOTICE: trigger_func(<NULL>) called: action = INSERT, when = BEFORE, level = STATEMENT
7412 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
7413 NOTICE: NEW: (1,insert)
7414 NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
7415 NOTICE: NEW: (1,insert)
7416 NOTICE: trigger_func(<NULL>) called: action = INSERT, when = AFTER, level = STATEMENT
7417 update rem1 set f2 = 'update' where f1 = 1;
7418 NOTICE: trigger_func(<NULL>) called: action = UPDATE, when = BEFORE, level = STATEMENT
7419 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
7420 NOTICE: OLD: (1,insert),NEW: (1,update)
7421 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
7422 NOTICE: OLD: (1,insert),NEW: (1,update)
7423 NOTICE: trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
7424 update rem1 set f2 = f2 || f2;
7425 NOTICE: trigger_func(<NULL>) called: action = UPDATE, when = BEFORE, level = STATEMENT
7426 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
7427 NOTICE: OLD: (1,update),NEW: (1,updateupdate)
7428 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
7429 NOTICE: OLD: (1,update),NEW: (1,updateupdate)
7430 NOTICE: trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
7432 NOTICE: trigger_func(<NULL>) called: action = TRUNCATE, when = BEFORE, level = STATEMENT
7433 NOTICE: trigger_func(<NULL>) called: action = TRUNCATE, when = AFTER, level = STATEMENT
7435 DROP TRIGGER trig_row_before ON rem1;
7436 DROP TRIGGER trig_row_after ON rem1;
7437 DROP TRIGGER trig_stmt_before ON rem1;
7438 DROP TRIGGER trig_stmt_after ON rem1;
7440 -- Test multiple AFTER ROW triggers on a foreign table
7441 CREATE TRIGGER trig_row_after1
7442 AFTER INSERT OR UPDATE OR DELETE ON rem1
7443 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7444 CREATE TRIGGER trig_row_after2
7445 AFTER INSERT OR UPDATE OR DELETE ON rem1
7446 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7447 insert into rem1 values(1,'insert');
7448 NOTICE: trig_row_after1(23, skidoo) AFTER ROW INSERT ON rem1
7449 NOTICE: NEW: (1,insert)
7450 NOTICE: trig_row_after2(23, skidoo) AFTER ROW INSERT ON rem1
7451 NOTICE: NEW: (1,insert)
7452 update rem1 set f2 = 'update' where f1 = 1;
7453 NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1
7454 NOTICE: OLD: (1,insert),NEW: (1,update)
7455 NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1
7456 NOTICE: OLD: (1,insert),NEW: (1,update)
7457 update rem1 set f2 = f2 || f2;
7458 NOTICE: trig_row_after1(23, skidoo) AFTER ROW UPDATE ON rem1
7459 NOTICE: OLD: (1,update),NEW: (1,updateupdate)
7460 NOTICE: trig_row_after2(23, skidoo) AFTER ROW UPDATE ON rem1
7461 NOTICE: OLD: (1,update),NEW: (1,updateupdate)
7463 NOTICE: trig_row_after1(23, skidoo) AFTER ROW DELETE ON rem1
7464 NOTICE: OLD: (1,updateupdate)
7465 NOTICE: trig_row_after2(23, skidoo) AFTER ROW DELETE ON rem1
7466 NOTICE: OLD: (1,updateupdate)
7468 DROP TRIGGER trig_row_after1 ON rem1;
7469 DROP TRIGGER trig_row_after2 ON rem1;
7470 -- Test WHEN conditions
7471 CREATE TRIGGER trig_row_before_insupd
7472 BEFORE INSERT OR UPDATE ON rem1
7474 WHEN (NEW.f2 like '%update%')
7475 EXECUTE PROCEDURE trigger_data(23,'skidoo');
7476 CREATE TRIGGER trig_row_after_insupd
7477 AFTER INSERT OR UPDATE ON rem1
7479 WHEN (NEW.f2 like '%update%')
7480 EXECUTE PROCEDURE trigger_data(23,'skidoo');
7481 -- Insert or update not matching: nothing happens
7482 INSERT INTO rem1 values(1, 'insert');
7483 UPDATE rem1 set f2 = 'test';
7484 -- Insert or update matching: triggers are fired
7485 INSERT INTO rem1 values(2, 'update');
7486 NOTICE: trig_row_before_insupd(23, skidoo) BEFORE ROW INSERT ON rem1
7487 NOTICE: NEW: (2,update)
7488 NOTICE: trig_row_after_insupd(23, skidoo) AFTER ROW INSERT ON rem1
7489 NOTICE: NEW: (2,update)
7490 UPDATE rem1 set f2 = 'update update' where f1 = '2';
7491 NOTICE: trig_row_before_insupd(23, skidoo) BEFORE ROW UPDATE ON rem1
7492 NOTICE: OLD: (2,update),NEW: (2,"update update")
7493 NOTICE: trig_row_after_insupd(23, skidoo) AFTER ROW UPDATE ON rem1
7494 NOTICE: OLD: (2,update),NEW: (2,"update update")
7495 CREATE TRIGGER trig_row_before_delete
7496 BEFORE DELETE ON rem1
7498 WHEN (OLD.f2 like '%update%')
7499 EXECUTE PROCEDURE trigger_data(23,'skidoo');
7500 CREATE TRIGGER trig_row_after_delete
7501 AFTER DELETE ON rem1
7503 WHEN (OLD.f2 like '%update%')
7504 EXECUTE PROCEDURE trigger_data(23,'skidoo');
7505 -- Trigger is fired for f1=2, not for f1=1
7507 NOTICE: trig_row_before_delete(23, skidoo) BEFORE ROW DELETE ON rem1
7508 NOTICE: OLD: (2,"update update")
7509 NOTICE: trig_row_after_delete(23, skidoo) AFTER ROW DELETE ON rem1
7510 NOTICE: OLD: (2,"update update")
7512 DROP TRIGGER trig_row_before_insupd ON rem1;
7513 DROP TRIGGER trig_row_after_insupd ON rem1;
7514 DROP TRIGGER trig_row_before_delete ON rem1;
7515 DROP TRIGGER trig_row_after_delete ON rem1;
7516 -- Test various RETURN statements in BEFORE triggers.
7517 CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$
7519 NEW.f2 := NEW.f2 || ' triggered !';
7522 $$ language plpgsql;
7523 CREATE TRIGGER trig_row_before_insupd
7524 BEFORE INSERT OR UPDATE ON rem1
7525 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
7526 -- The new values should have 'triggered' appended
7527 INSERT INTO rem1 values(1, 'insert');
7530 ----+--------------------
7531 1 | insert triggered !
7534 INSERT INTO rem1 values(2, 'insert') RETURNING f2;
7536 --------------------
7542 ----+--------------------
7543 1 | insert triggered !
7544 2 | insert triggered !
7547 UPDATE rem1 set f2 = '';
7555 UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
7557 --------------------
7564 ----+--------------------
7565 1 | skidoo triggered !
7566 2 | skidoo triggered !
7569 EXPLAIN (verbose, costs off)
7570 UPDATE rem1 set f1 = 10; -- all columns should be transmitted
7572 -----------------------------------------------------------------------
7573 Update on public.rem1
7574 Remote SQL: UPDATE public.loc1 SET f1 = $2, f2 = $3 WHERE ctid = $1
7575 -> Foreign Scan on public.rem1
7576 Output: 10, ctid, rem1.*
7577 Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
7580 UPDATE rem1 set f1 = 10;
7583 ----+--------------------------------
7584 10 | skidoo triggered ! triggered !
7585 10 | skidoo triggered ! triggered !
7589 -- Add a second trigger, to check that the changes are propagated correctly
7590 -- from trigger to trigger
7591 CREATE TRIGGER trig_row_before_insupd2
7592 BEFORE INSERT OR UPDATE ON rem1
7593 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
7594 INSERT INTO rem1 values(1, 'insert');
7597 ----+--------------------------------
7598 1 | insert triggered ! triggered !
7601 INSERT INTO rem1 values(2, 'insert') RETURNING f2;
7603 --------------------------------
7604 insert triggered ! triggered !
7609 ----+--------------------------------
7610 1 | insert triggered ! triggered !
7611 2 | insert triggered ! triggered !
7614 UPDATE rem1 set f2 = '';
7617 ----+--------------------------
7618 1 | triggered ! triggered !
7619 2 | triggered ! triggered !
7622 UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
7624 --------------------------------
7625 skidoo triggered ! triggered !
7626 skidoo triggered ! triggered !
7631 ----+--------------------------------
7632 1 | skidoo triggered ! triggered !
7633 2 | skidoo triggered ! triggered !
7636 DROP TRIGGER trig_row_before_insupd ON rem1;
7637 DROP TRIGGER trig_row_before_insupd2 ON rem1;
7639 INSERT INTO rem1 VALUES (1, 'test');
7640 -- Test with a trigger returning NULL
7641 CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$
7645 $$ language plpgsql;
7646 CREATE TRIGGER trig_null
7647 BEFORE INSERT OR UPDATE OR DELETE ON rem1
7648 FOR EACH ROW EXECUTE PROCEDURE trig_null();
7649 -- Nothing should have changed.
7650 INSERT INTO rem1 VALUES (2, 'test2');
7657 UPDATE rem1 SET f2 = 'test2';
7671 DROP TRIGGER trig_null ON rem1;
7673 -- Test a combination of local and remote triggers
7674 CREATE TRIGGER trig_row_before
7675 BEFORE INSERT OR UPDATE OR DELETE ON rem1
7676 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7677 CREATE TRIGGER trig_row_after
7678 AFTER INSERT OR UPDATE OR DELETE ON rem1
7679 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7680 CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON loc1
7681 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
7682 INSERT INTO rem1(f2) VALUES ('test');
7683 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
7684 NOTICE: NEW: (12,test)
7685 NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
7686 NOTICE: NEW: (12,"test triggered !")
7687 UPDATE rem1 SET f2 = 'testo';
7688 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
7689 NOTICE: OLD: (12,"test triggered !"),NEW: (12,testo)
7690 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
7691 NOTICE: OLD: (12,"test triggered !"),NEW: (12,"testo triggered !")
7692 -- Test returning a system attribute
7693 INSERT INTO rem1(f2) VALUES ('test') RETURNING ctid;
7694 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
7695 NOTICE: NEW: (13,test)
7696 NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
7697 NOTICE: NEW: (13,"test triggered !")
7704 DROP TRIGGER trig_row_before ON rem1;
7705 DROP TRIGGER trig_row_after ON rem1;
7706 DROP TRIGGER trig_local_before ON loc1;
7707 -- Test direct foreign table modification functionality
7708 EXPLAIN (verbose, costs off)
7709 DELETE FROM rem1; -- can be pushed down
7711 ---------------------------------------------
7712 Delete on public.rem1
7713 -> Foreign Delete on public.rem1
7714 Remote SQL: DELETE FROM public.loc1
7717 EXPLAIN (verbose, costs off)
7718 DELETE FROM rem1 WHERE false; -- currently can't be pushed down
7720 -------------------------------------------------------
7721 Delete on public.rem1
7722 Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1
7725 One-Time Filter: false
7728 -- Test with statement-level triggers
7729 CREATE TRIGGER trig_stmt_before
7730 BEFORE DELETE OR INSERT OR UPDATE ON rem1
7731 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
7732 EXPLAIN (verbose, costs off)
7733 UPDATE rem1 set f2 = ''; -- can be pushed down
7735 ----------------------------------------------------------
7736 Update on public.rem1
7737 -> Foreign Update on public.rem1
7738 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7741 EXPLAIN (verbose, costs off)
7742 DELETE FROM rem1; -- can be pushed down
7744 ---------------------------------------------
7745 Delete on public.rem1
7746 -> Foreign Delete on public.rem1
7747 Remote SQL: DELETE FROM public.loc1
7750 DROP TRIGGER trig_stmt_before ON rem1;
7751 CREATE TRIGGER trig_stmt_after
7752 AFTER DELETE OR INSERT OR UPDATE ON rem1
7753 FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
7754 EXPLAIN (verbose, costs off)
7755 UPDATE rem1 set f2 = ''; -- can be pushed down
7757 ----------------------------------------------------------
7758 Update on public.rem1
7759 -> Foreign Update on public.rem1
7760 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7763 EXPLAIN (verbose, costs off)
7764 DELETE FROM rem1; -- can be pushed down
7766 ---------------------------------------------
7767 Delete on public.rem1
7768 -> Foreign Delete on public.rem1
7769 Remote SQL: DELETE FROM public.loc1
7772 DROP TRIGGER trig_stmt_after ON rem1;
7773 -- Test with row-level ON INSERT triggers
7774 CREATE TRIGGER trig_row_before_insert
7775 BEFORE INSERT ON rem1
7776 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7777 EXPLAIN (verbose, costs off)
7778 UPDATE rem1 set f2 = ''; -- can be pushed down
7780 ----------------------------------------------------------
7781 Update on public.rem1
7782 -> Foreign Update on public.rem1
7783 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7786 EXPLAIN (verbose, costs off)
7787 DELETE FROM rem1; -- can be pushed down
7789 ---------------------------------------------
7790 Delete on public.rem1
7791 -> Foreign Delete on public.rem1
7792 Remote SQL: DELETE FROM public.loc1
7795 DROP TRIGGER trig_row_before_insert ON rem1;
7796 CREATE TRIGGER trig_row_after_insert
7797 AFTER INSERT ON rem1
7798 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7799 EXPLAIN (verbose, costs off)
7800 UPDATE rem1 set f2 = ''; -- can be pushed down
7802 ----------------------------------------------------------
7803 Update on public.rem1
7804 -> Foreign Update on public.rem1
7805 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7808 EXPLAIN (verbose, costs off)
7809 DELETE FROM rem1; -- can be pushed down
7811 ---------------------------------------------
7812 Delete on public.rem1
7813 -> Foreign Delete on public.rem1
7814 Remote SQL: DELETE FROM public.loc1
7817 DROP TRIGGER trig_row_after_insert ON rem1;
7818 -- Test with row-level ON UPDATE triggers
7819 CREATE TRIGGER trig_row_before_update
7820 BEFORE UPDATE ON rem1
7821 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7822 EXPLAIN (verbose, costs off)
7823 UPDATE rem1 set f2 = ''; -- can't be pushed down
7825 -----------------------------------------------------------------------
7826 Update on public.rem1
7827 Remote SQL: UPDATE public.loc1 SET f1 = $2, f2 = $3 WHERE ctid = $1
7828 -> Foreign Scan on public.rem1
7829 Output: ''::text, ctid, rem1.*
7830 Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
7833 EXPLAIN (verbose, costs off)
7834 DELETE FROM rem1; -- can be pushed down
7836 ---------------------------------------------
7837 Delete on public.rem1
7838 -> Foreign Delete on public.rem1
7839 Remote SQL: DELETE FROM public.loc1
7842 DROP TRIGGER trig_row_before_update ON rem1;
7843 CREATE TRIGGER trig_row_after_update
7844 AFTER 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 f2 = $2 WHERE ctid = $1 RETURNING f1, f2
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_after_update ON rem1;
7867 -- Test with row-level ON DELETE triggers
7868 CREATE TRIGGER trig_row_before_delete
7869 BEFORE DELETE ON rem1
7870 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7871 EXPLAIN (verbose, costs off)
7872 UPDATE rem1 set f2 = ''; -- can be pushed down
7874 ----------------------------------------------------------
7875 Update on public.rem1
7876 -> Foreign Update on public.rem1
7877 Remote SQL: UPDATE public.loc1 SET f2 = ''::text
7880 EXPLAIN (verbose, costs off)
7881 DELETE FROM rem1; -- can't be pushed down
7883 ---------------------------------------------------------------------
7884 Delete on public.rem1
7885 Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1
7886 -> Foreign Scan on public.rem1
7887 Output: ctid, rem1.*
7888 Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
7891 DROP TRIGGER trig_row_before_delete ON rem1;
7892 CREATE TRIGGER trig_row_after_delete
7893 AFTER 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 RETURNING f1, f2
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_after_delete ON rem1;
7916 -- ===================================================================
7917 -- test inheritance features
7918 -- ===================================================================
7919 CREATE TABLE a (aa TEXT);
7920 CREATE TABLE loct (aa TEXT, bb TEXT);
7921 ALTER TABLE a SET (autovacuum_enabled = 'false');
7922 ALTER TABLE loct SET (autovacuum_enabled = 'false');
7923 CREATE FOREIGN TABLE b (bb TEXT) INHERITS (a)
7924 SERVER loopback OPTIONS (table_name 'loct');
7925 INSERT INTO a(aa) VALUES('aaa');
7926 INSERT INTO a(aa) VALUES('aaaa');
7927 INSERT INTO a(aa) VALUES('aaaaa');
7928 INSERT INTO b(aa) VALUES('bbb');
7929 INSERT INTO b(aa) VALUES('bbbb');
7930 INSERT INTO b(aa) VALUES('bbbbb');
7931 SELECT tableoid::regclass, * FROM a;
7942 SELECT tableoid::regclass, * FROM b;
7944 ----------+-------+----
7950 SELECT tableoid::regclass, * FROM ONLY a;
7958 UPDATE a SET aa = 'zzzzzz' WHERE aa LIKE 'aaaa%';
7959 SELECT tableoid::regclass, * FROM a;
7970 SELECT tableoid::regclass, * FROM b;
7972 ----------+-------+----
7978 SELECT tableoid::regclass, * FROM ONLY a;
7986 UPDATE b SET aa = 'new';
7987 SELECT tableoid::regclass, * FROM a;
7998 SELECT tableoid::regclass, * FROM b;
8000 ----------+-----+----
8006 SELECT tableoid::regclass, * FROM ONLY a;
8014 UPDATE a SET aa = 'newtoo';
8015 SELECT tableoid::regclass, * FROM a;
8026 SELECT tableoid::regclass, * FROM b;
8028 ----------+--------+----
8034 SELECT tableoid::regclass, * FROM ONLY a;
8043 SELECT tableoid::regclass, * FROM a;
8048 SELECT tableoid::regclass, * FROM b;
8050 ----------+----+----
8053 SELECT tableoid::regclass, * FROM ONLY a;
8058 DROP TABLE a CASCADE;
8059 NOTICE: drop cascades to foreign table b
8061 -- Check SELECT FOR UPDATE/SHARE with an inherited source table
8062 create table loct1 (f1 int, f2 int, f3 int);
8063 create table loct2 (f1 int, f2 int, f3 int);
8064 alter table loct1 set (autovacuum_enabled = 'false');
8065 alter table loct2 set (autovacuum_enabled = 'false');
8066 create table foo (f1 int, f2 int);
8067 create foreign table foo2 (f3 int) inherits (foo)
8068 server loopback options (table_name 'loct1');
8069 create table bar (f1 int, f2 int);
8070 create foreign table bar2 (f3 int) inherits (bar)
8071 server loopback options (table_name 'loct2');
8072 alter table foo set (autovacuum_enabled = 'false');
8073 alter table bar set (autovacuum_enabled = 'false');
8074 insert into foo values(1,1);
8075 insert into foo values(3,3);
8076 insert into foo2 values(2,2,2);
8077 insert into foo2 values(4,4,4);
8078 insert into bar values(1,11);
8079 insert into bar values(2,22);
8080 insert into bar values(6,66);
8081 insert into bar2 values(3,33,33);
8082 insert into bar2 values(4,44,44);
8083 insert into bar2 values(7,77,77);
8084 explain (verbose, costs off)
8085 select * from bar where f1 in (select f1 from foo) for update;
8087 ----------------------------------------------------------------------------------------------
8089 Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid
8091 Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid
8093 Hash Cond: (bar.f1 = foo.f1)
8095 -> Seq Scan on public.bar bar_1
8096 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
8097 -> Foreign Scan on public.bar2 bar_2
8098 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
8099 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
8101 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8103 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8106 -> Seq Scan on public.foo foo_1
8107 Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid
8108 -> Foreign Scan on public.foo2 foo_2
8109 Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid
8110 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
8113 select * from bar where f1 in (select f1 from foo) for update;
8122 explain (verbose, costs off)
8123 select * from bar where f1 in (select f1 from foo) for share;
8125 ----------------------------------------------------------------------------------------------
8127 Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid
8129 Output: bar.f1, bar.f2, bar.ctid, foo.ctid, bar.*, bar.tableoid, foo.*, foo.tableoid
8131 Hash Cond: (bar.f1 = foo.f1)
8133 -> Seq Scan on public.bar bar_1
8134 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
8135 -> Foreign Scan on public.bar2 bar_2
8136 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
8137 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
8139 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8141 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8144 -> Seq Scan on public.foo foo_1
8145 Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid
8146 -> Foreign Scan on public.foo2 foo_2
8147 Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid
8148 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
8151 select * from bar where f1 in (select f1 from foo) for share;
8160 -- Now check SELECT FOR UPDATE/SHARE with an inherited source table,
8161 -- where the parent is itself a foreign table
8162 create table loct4 (f1 int, f2 int, f3 int);
8163 create foreign table foo2child (f3 int) inherits (foo2)
8164 server loopback options (table_name 'loct4');
8165 NOTICE: moving and merging column "f3" with inherited definition
8166 DETAIL: User-specified column moved to the position of the inherited column.
8167 explain (verbose, costs off)
8168 select * from bar where f1 in (select f1 from foo2) for share;
8170 --------------------------------------------------------------------------------------
8172 Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.tableoid
8174 Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.tableoid
8176 Hash Cond: (bar.f1 = foo2.f1)
8178 -> Seq Scan on public.bar bar_1
8179 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
8180 -> Foreign Scan on public.bar2 bar_2
8181 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
8182 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
8184 Output: foo2.*, foo2.f1, foo2.tableoid
8186 Output: foo2.*, foo2.f1, foo2.tableoid
8189 -> Foreign Scan on public.foo2 foo2_1
8190 Output: foo2_1.*, foo2_1.f1, foo2_1.tableoid
8191 Remote SQL: SELECT f1, f2, f3 FROM public.loct1
8192 -> Foreign Scan on public.foo2child foo2_2
8193 Output: foo2_2.*, foo2_2.f1, foo2_2.tableoid
8194 Remote SQL: SELECT f1, f2, f3 FROM public.loct4
8197 select * from bar where f1 in (select f1 from foo2) for share;
8204 drop foreign table foo2child;
8205 -- And with a local child relation of the foreign table parent
8206 create table foo2child (f3 int) inherits (foo2);
8207 NOTICE: moving and merging column "f3" with inherited definition
8208 DETAIL: User-specified column moved to the position of the inherited column.
8209 explain (verbose, costs off)
8210 select * from bar where f1 in (select f1 from foo2) for share;
8212 -------------------------------------------------------------------------------------------------
8214 Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.ctid, foo2.tableoid
8216 Output: bar.f1, bar.f2, bar.ctid, foo2.*, bar.*, bar.tableoid, foo2.ctid, foo2.tableoid
8218 Hash Cond: (bar.f1 = foo2.f1)
8220 -> Seq Scan on public.bar bar_1
8221 Output: bar_1.f1, bar_1.f2, bar_1.ctid, bar_1.*, bar_1.tableoid
8222 -> Foreign Scan on public.bar2 bar_2
8223 Output: bar_2.f1, bar_2.f2, bar_2.ctid, bar_2.*, bar_2.tableoid
8224 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
8226 Output: foo2.*, foo2.f1, foo2.ctid, foo2.tableoid
8228 Output: foo2.*, foo2.f1, foo2.ctid, foo2.tableoid
8231 -> Foreign Scan on public.foo2 foo2_1
8232 Output: foo2_1.*, foo2_1.f1, foo2_1.ctid, foo2_1.tableoid
8233 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
8234 -> Seq Scan on public.foo2child foo2_2
8235 Output: foo2_2.*, foo2_2.f1, foo2_2.ctid, foo2_2.tableoid
8238 select * from bar where f1 in (select f1 from foo2) for share;
8245 drop table foo2child;
8246 -- Check UPDATE with inherited target and an inherited source table
8247 explain (verbose, costs off)
8248 update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
8250 -------------------------------------------------------------------------------------------------------
8251 Update on public.bar
8252 Update on public.bar bar_1
8253 Foreign Update on public.bar2 bar_2
8254 Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
8256 Output: (bar.f2 + 100), foo.ctid, bar.tableoid, bar.ctid, (NULL::record), foo.*, foo.tableoid
8258 Hash Cond: (bar.f1 = foo.f1)
8260 -> Seq Scan on public.bar bar_1
8261 Output: bar_1.f2, bar_1.f1, bar_1.tableoid, bar_1.ctid, NULL::record
8262 -> Foreign Scan on public.bar2 bar_2
8263 Output: bar_2.f2, bar_2.f1, bar_2.tableoid, bar_2.ctid, bar_2.*
8264 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
8266 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8268 Output: foo.ctid, foo.f1, foo.*, foo.tableoid
8271 -> Seq Scan on public.foo foo_1
8272 Output: foo_1.ctid, foo_1.f1, foo_1.*, foo_1.tableoid
8273 -> Foreign Scan on public.foo2 foo_2
8274 Output: foo_2.ctid, foo_2.f1, foo_2.*, foo_2.tableoid
8275 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
8278 update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
8279 select tableoid::regclass, * from bar order by 1,2;
8281 ----------+----+-----
8290 -- Check UPDATE with inherited target and an appendrel subquery
8291 explain (verbose, costs off)
8292 update bar set f2 = f2 + 100
8294 ( select f1 from foo union all select f1+3 from foo ) ss
8295 where bar.f1 = ss.f1;
8297 ------------------------------------------------------------------------------------------------
8298 Update on public.bar
8299 Update on public.bar bar_1
8300 Foreign Update on public.bar2 bar_2
8301 Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
8303 Output: (bar.f2 + 100), (ROW(foo.f1)), bar.tableoid, bar.ctid, (NULL::record)
8304 Merge Cond: (bar.f1 = foo.f1)
8306 Output: bar.f2, bar.f1, bar.tableoid, bar.ctid, (NULL::record)
8309 -> Seq Scan on public.bar bar_1
8310 Output: bar_1.f2, bar_1.f1, bar_1.tableoid, bar_1.ctid, NULL::record
8311 -> Foreign Scan on public.bar2 bar_2
8312 Output: bar_2.f2, bar_2.f1, bar_2.tableoid, bar_2.ctid, bar_2.*
8313 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
8315 Output: (ROW(foo.f1)), foo.f1
8318 -> Seq Scan on public.foo
8319 Output: ROW(foo.f1), foo.f1
8320 -> Foreign Scan on public.foo2 foo_1
8321 Output: ROW(foo_1.f1), foo_1.f1
8322 Remote SQL: SELECT f1 FROM public.loct1
8323 -> Seq Scan on public.foo foo_2
8324 Output: ROW((foo_2.f1 + 3)), (foo_2.f1 + 3)
8325 -> Foreign Scan on public.foo2 foo_3
8326 Output: ROW((foo_3.f1 + 3)), (foo_3.f1 + 3)
8327 Remote SQL: SELECT f1 FROM public.loct1
8330 update bar set f2 = f2 + 100
8332 ( select f1 from foo union all select f1+3 from foo ) ss
8333 where bar.f1 = ss.f1;
8334 select tableoid::regclass, * from bar order by 1,2;
8336 ----------+----+-----
8345 -- Test forcing the remote server to produce sorted data for a merge join,
8346 -- but the foreign table is an inheritance child.
8347 truncate table loct1;
8348 truncate table only foo;
8349 \set num_rows_foo 2000
8350 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);
8351 insert into foo select generate_series(1, :num_rows_foo, 2), generate_series(1, :num_rows_foo, 2);
8352 SET enable_hashjoin to false;
8353 SET enable_nestloop to false;
8354 alter foreign table foo2 options (use_remote_estimate 'true');
8355 create index i_loct1_f1 on loct1(f1);
8356 create index i_foo_f1 on foo(f1);
8359 -- inner join; expressions in the clauses appear in the equivalence class list
8360 explain (verbose, costs off)
8361 select foo.f1, loct1.f1 from foo join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
8363 --------------------------------------------------------------------------------------------------
8365 Output: foo.f1, loct1.f1, foo.f2
8367 Output: foo.f1, loct1.f1, foo.f2
8370 Output: foo.f1, loct1.f1, foo.f2
8371 Merge Cond: (foo.f1 = loct1.f1)
8374 -> Index Scan using i_foo_f1 on public.foo foo_1
8375 Output: foo_1.f1, foo_1.f2
8376 -> Foreign Scan on public.foo2 foo_2
8377 Output: foo_2.f1, foo_2.f2
8378 Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
8379 -> Index Only Scan using i_loct1_f1 on public.loct1
8383 select foo.f1, loct1.f1 from foo join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
8398 -- outer join; expressions in the clauses do not appear in equivalence class
8399 -- list but no output change as compared to the previous query
8400 explain (verbose, costs off)
8401 select foo.f1, loct1.f1 from foo left join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
8403 --------------------------------------------------------------------------------------------------
8405 Output: foo.f1, loct1.f1, foo.f2
8407 Output: foo.f1, loct1.f1, foo.f2
8410 Output: foo.f1, loct1.f1, foo.f2
8411 Merge Cond: (foo.f1 = loct1.f1)
8414 -> Index Scan using i_foo_f1 on public.foo foo_1
8415 Output: foo_1.f1, foo_1.f2
8416 -> Foreign Scan on public.foo2 foo_2
8417 Output: foo_2.f1, foo_2.f2
8418 Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
8419 -> Index Only Scan using i_loct1_f1 on public.loct1
8423 select foo.f1, loct1.f1 from foo left join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
8438 RESET enable_hashjoin;
8439 RESET enable_nestloop;
8440 -- Test that WHERE CURRENT OF is not supported
8442 declare c cursor for select * from bar where f1 = 7;
8449 update bar set f2 = null where current of c;
8450 ERROR: WHERE CURRENT OF is not supported for this table type
8452 explain (verbose, costs off)
8453 delete from foo where f1 < 5 returning *;
8455 --------------------------------------------------------------------------------------
8456 Delete on public.foo
8457 Output: foo_1.f1, foo_1.f2
8458 Delete on public.foo foo_1
8459 Foreign Delete on public.foo2 foo_2
8461 -> Index Scan using i_foo_f1 on public.foo foo_1
8462 Output: foo_1.tableoid, foo_1.ctid
8463 Index Cond: (foo_1.f1 < 5)
8464 -> Foreign Delete on public.foo2 foo_2
8465 Remote SQL: DELETE FROM public.loct1 WHERE ((f1 < 5)) RETURNING f1, f2
8468 delete from foo where f1 < 5 returning *;
8478 explain (verbose, costs off)
8479 update bar set f2 = f2 + 100 returning *;
8481 ------------------------------------------------------------------------------------------
8482 Update on public.bar
8483 Output: bar_1.f1, bar_1.f2
8484 Update on public.bar bar_1
8485 Foreign Update on public.bar2 bar_2
8487 Output: (bar.f2 + 100), bar.tableoid, bar.ctid, (NULL::record)
8489 -> Seq Scan on public.bar bar_1
8490 Output: bar_1.f2, bar_1.tableoid, bar_1.ctid, NULL::record
8491 -> Foreign Update on public.bar2 bar_2
8492 Remote SQL: UPDATE public.loct2 SET f2 = (f2 + 100) RETURNING f1, f2
8495 update bar set f2 = f2 + 100 returning *;
8506 -- Test that UPDATE/DELETE with inherited target works with row-level triggers
8507 CREATE TRIGGER trig_row_before
8508 BEFORE UPDATE OR DELETE ON bar2
8509 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
8510 CREATE TRIGGER trig_row_after
8511 AFTER UPDATE OR DELETE ON bar2
8512 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
8513 explain (verbose, costs off)
8514 update bar set f2 = f2 + 100;
8516 --------------------------------------------------------------------------------------------------------
8517 Update on public.bar
8518 Update on public.bar bar_1
8519 Foreign Update on public.bar2 bar_2
8520 Remote SQL: UPDATE public.loct2 SET f1 = $2, f2 = $3, f3 = $4 WHERE ctid = $1 RETURNING f1, f2, f3
8522 Output: (bar.f2 + 100), bar.tableoid, bar.ctid, (NULL::record)
8524 -> Seq Scan on public.bar bar_1
8525 Output: bar_1.f2, bar_1.tableoid, bar_1.ctid, NULL::record
8526 -> Foreign Scan on public.bar2 bar_2
8527 Output: bar_2.f2, bar_2.tableoid, bar_2.ctid, bar_2.*
8528 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
8531 update bar set f2 = f2 + 100;
8532 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
8533 NOTICE: OLD: (3,333,33),NEW: (3,433,33)
8534 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
8535 NOTICE: OLD: (4,344,44),NEW: (4,444,44)
8536 NOTICE: trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
8537 NOTICE: OLD: (7,277,77),NEW: (7,377,77)
8538 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
8539 NOTICE: OLD: (3,333,33),NEW: (3,433,33)
8540 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
8541 NOTICE: OLD: (4,344,44),NEW: (4,444,44)
8542 NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
8543 NOTICE: OLD: (7,277,77),NEW: (7,377,77)
8544 explain (verbose, costs off)
8545 delete from bar where f2 < 400;
8547 ---------------------------------------------------------------------------------------------------
8548 Delete on public.bar
8549 Delete on public.bar bar_1
8550 Foreign Delete on public.bar2 bar_2
8551 Remote SQL: DELETE FROM public.loct2 WHERE ctid = $1 RETURNING f1, f2, f3
8553 -> Seq Scan on public.bar bar_1
8554 Output: bar_1.tableoid, bar_1.ctid, NULL::record
8555 Filter: (bar_1.f2 < 400)
8556 -> Foreign Scan on public.bar2 bar_2
8557 Output: bar_2.tableoid, bar_2.ctid, bar_2.*
8558 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 WHERE ((f2 < 400)) FOR UPDATE
8561 delete from bar where f2 < 400;
8562 NOTICE: trig_row_before(23, skidoo) BEFORE ROW DELETE ON bar2
8563 NOTICE: OLD: (7,377,77)
8564 NOTICE: trig_row_after(23, skidoo) AFTER ROW DELETE ON bar2
8565 NOTICE: OLD: (7,377,77)
8567 drop table foo cascade;
8568 NOTICE: drop cascades to foreign table foo2
8569 drop table bar cascade;
8570 NOTICE: drop cascades to foreign table bar2
8573 -- Test pushing down UPDATE/DELETE joins to the remote server
8574 create table parent (a int, b text);
8575 create table loct1 (a int, b text);
8576 create table loct2 (a int, b text);
8577 create foreign table remt1 (a int, b text)
8578 server loopback options (table_name 'loct1');
8579 create foreign table remt2 (a int, b text)
8580 server loopback options (table_name 'loct2');
8581 alter foreign table remt1 inherit parent;
8582 insert into remt1 values (1, 'foo');
8583 insert into remt1 values (2, 'bar');
8584 insert into remt2 values (1, 'foo');
8585 insert into remt2 values (2, 'bar');
8588 explain (verbose, costs off)
8589 update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a returning *;
8591 ----------------------------------------------------------------------------------------------------------------
8592 Update on public.parent
8593 Output: parent_1.a, parent_1.b, remt2.a, remt2.b
8594 Update on public.parent parent_1
8595 Foreign Update on public.remt1 parent_2
8596 Remote SQL: UPDATE public.loct1 SET b = $2 WHERE ctid = $1 RETURNING a, b
8598 Output: (parent.b || remt2.b), remt2.*, remt2.a, remt2.b, parent.tableoid, parent.ctid, (NULL::record)
8599 Join Filter: (parent.a = remt2.a)
8601 -> Seq Scan on public.parent parent_1
8602 Output: parent_1.b, parent_1.a, parent_1.tableoid, parent_1.ctid, NULL::record
8603 -> Foreign Scan on public.remt1 parent_2
8604 Output: parent_2.b, parent_2.a, parent_2.tableoid, parent_2.ctid, parent_2.*
8605 Remote SQL: SELECT a, b, ctid FROM public.loct1 FOR UPDATE
8607 Output: remt2.b, remt2.*, remt2.a
8608 -> Foreign Scan on public.remt2
8609 Output: remt2.b, remt2.*, remt2.a
8610 Remote SQL: SELECT a, b FROM public.loct2
8613 update parent set b = parent.b || remt2.b from remt2 where parent.a = remt2.a returning *;
8615 ---+--------+---+-----
8616 1 | foofoo | 1 | foo
8617 2 | barbar | 2 | bar
8620 explain (verbose, costs off)
8621 delete from parent using remt2 where parent.a = remt2.a returning parent;
8623 -----------------------------------------------------------------------------
8624 Delete on public.parent
8626 Delete on public.parent parent_1
8627 Foreign Delete on public.remt1 parent_2
8628 Remote SQL: DELETE FROM public.loct1 WHERE ctid = $1 RETURNING a, b
8630 Output: remt2.*, parent.tableoid, parent.ctid
8631 Join Filter: (parent.a = remt2.a)
8633 -> Seq Scan on public.parent parent_1
8634 Output: parent_1.a, parent_1.tableoid, parent_1.ctid
8635 -> Foreign Scan on public.remt1 parent_2
8636 Output: parent_2.a, parent_2.tableoid, parent_2.ctid
8637 Remote SQL: SELECT a, ctid FROM public.loct1 FOR UPDATE
8639 Output: remt2.*, remt2.a
8640 -> Foreign Scan on public.remt2
8641 Output: remt2.*, remt2.a
8642 Remote SQL: SELECT a, b FROM public.loct2
8645 delete from parent using remt2 where parent.a = remt2.a returning parent;
8653 drop foreign table remt1;
8654 drop foreign table remt2;
8658 -- ===================================================================
8659 -- test tuple routing for foreign-table partitions
8660 -- ===================================================================
8661 -- Test insert tuple routing
8662 create table itrtest (a int, b text) partition by list (a);
8663 create table loct1 (a int check (a in (1)), b text);
8664 create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1');
8665 create table loct2 (a int check (a in (2)), b text);
8666 create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2');
8667 alter table itrtest attach partition remp1 for values in (1);
8668 alter table itrtest attach partition remp2 for values in (2);
8669 insert into itrtest values (1, 'foo');
8670 insert into itrtest values (1, 'bar') returning *;
8676 insert into itrtest values (2, 'baz');
8677 insert into itrtest values (2, 'qux') returning *;
8683 insert into itrtest values (1, 'test1'), (2, 'test2') returning *;
8690 select tableoid::regclass, * FROM itrtest;
8692 ----------+---+-------
8701 select tableoid::regclass, * FROM remp1;
8703 ----------+---+-------
8709 select tableoid::regclass, * FROM remp2;
8711 ----------+-------+---
8717 delete from itrtest;
8718 -- MERGE ought to fail cleanly
8719 merge into itrtest using (select 1, 'foo') as source on (true)
8720 when matched then do nothing;
8721 ERROR: cannot execute MERGE on relation "remp1"
8722 DETAIL: This operation is not supported for foreign tables.
8723 create unique index loct1_idx on loct1 (a);
8724 -- DO NOTHING without an inference specification is supported
8725 insert into itrtest values (1, 'foo') on conflict do nothing returning *;
8731 insert into itrtest values (1, 'foo') on conflict do nothing returning *;
8736 -- But other cases are not supported
8737 insert into itrtest values (1, 'bar') on conflict (a) do nothing;
8738 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
8739 insert into itrtest values (1, 'bar') on conflict (a) do update set b = excluded.b;
8740 ERROR: there is no unique or exclusion constraint matching the ON CONFLICT specification
8741 select tableoid::regclass, * FROM itrtest;
8743 ----------+---+-----
8747 delete from itrtest;
8748 drop index loct1_idx;
8749 -- Test that remote triggers work with insert tuple routing
8750 create function br_insert_trigfunc() returns trigger as $$
8752 new.b := new.b || ' triggered !';
8755 $$ language plpgsql;
8756 create trigger loct1_br_insert_trigger before insert on loct1
8757 for each row execute procedure br_insert_trigfunc();
8758 create trigger loct2_br_insert_trigger before insert on loct2
8759 for each row execute procedure br_insert_trigfunc();
8760 -- The new values are concatenated with ' triggered !'
8761 insert into itrtest values (1, 'foo') returning *;
8763 ---+-----------------
8767 insert into itrtest values (2, 'qux') returning *;
8769 ---+-----------------
8773 insert into itrtest values (1, 'test1'), (2, 'test2') returning *;
8775 ---+-------------------
8776 1 | test1 triggered !
8777 2 | test2 triggered !
8780 with result as (insert into itrtest values (1, 'test1'), (2, 'test2') returning *) select * from result;
8782 ---+-------------------
8783 1 | test1 triggered !
8784 2 | test2 triggered !
8787 drop trigger loct1_br_insert_trigger on loct1;
8788 drop trigger loct2_br_insert_trigger on loct2;
8792 -- Test update tuple routing
8793 create table utrtest (a int, b text) partition by list (a);
8794 create table loct (a int check (a in (1)), b text);
8795 create foreign table remp (a int check (a in (1)), b text) server loopback options (table_name 'loct');
8796 create table locp (a int check (a in (2)), b text);
8797 alter table utrtest attach partition remp for values in (1);
8798 alter table utrtest attach partition locp for values in (2);
8799 insert into utrtest values (1, 'foo');
8800 insert into utrtest values (2, 'qux');
8801 select tableoid::regclass, * FROM utrtest;
8803 ----------+---+-----
8808 select tableoid::regclass, * FROM remp;
8810 ----------+---+-----
8814 select tableoid::regclass, * FROM locp;
8816 ----------+---+-----
8820 -- It's not allowed to move a row from a partition that is foreign to another
8821 update utrtest set a = 2 where b = 'foo' returning *;
8822 ERROR: new row for relation "loct" violates check constraint "loct_a_check"
8823 DETAIL: Failing row contains (2, foo).
8824 CONTEXT: remote SQL command: UPDATE public.loct SET a = 2 WHERE ((b = 'foo')) RETURNING a, b
8825 -- But the reverse is allowed
8826 update utrtest set a = 1 where b = 'qux' returning *;
8827 ERROR: cannot route tuples into foreign table to be updated "remp"
8828 select tableoid::regclass, * FROM utrtest;
8830 ----------+---+-----
8835 select tableoid::regclass, * FROM remp;
8837 ----------+---+-----
8841 select tableoid::regclass, * FROM locp;
8843 ----------+---+-----
8847 -- The executor should not let unexercised FDWs shut down
8848 update utrtest set a = 1 where b = 'foo';
8849 -- Test that remote triggers work with update tuple routing
8850 create trigger loct_br_insert_trigger before insert on loct
8851 for each row execute procedure br_insert_trigfunc();
8852 delete from utrtest;
8853 insert into utrtest values (2, 'qux');
8854 -- Check case where the foreign partition is a subplan target rel
8855 explain (verbose, costs off)
8856 update utrtest set a = 1 where a = 1 or a = 2 returning *;
8858 ----------------------------------------------------------------------------------------------------
8859 Update on public.utrtest
8860 Output: utrtest_1.a, utrtest_1.b
8861 Foreign Update on public.remp utrtest_1
8862 Update on public.locp utrtest_2
8864 -> Foreign Update on public.remp utrtest_1
8865 Remote SQL: UPDATE public.loct SET a = 1 WHERE (((a = 1) OR (a = 2))) RETURNING a, b
8866 -> Seq Scan on public.locp utrtest_2
8867 Output: 1, utrtest_2.tableoid, utrtest_2.ctid, NULL::record
8868 Filter: ((utrtest_2.a = 1) OR (utrtest_2.a = 2))
8871 -- The new values are concatenated with ' triggered !'
8872 update utrtest set a = 1 where a = 1 or a = 2 returning *;
8873 ERROR: cannot route tuples into foreign table to be updated "remp"
8874 delete from utrtest;
8875 insert into utrtest values (2, 'qux');
8876 -- Check case where the foreign partition isn't a subplan target rel
8877 explain (verbose, costs off)
8878 update utrtest set a = 1 where a = 2 returning *;
8880 -------------------------------------------------------
8881 Update on public.utrtest
8882 Output: utrtest_1.a, utrtest_1.b
8883 Update on public.locp utrtest_1
8884 -> Seq Scan on public.locp utrtest_1
8885 Output: 1, utrtest_1.tableoid, utrtest_1.ctid
8886 Filter: (utrtest_1.a = 2)
8889 -- The new values are concatenated with ' triggered !'
8890 update utrtest set a = 1 where a = 2 returning *;
8892 ---+-----------------
8896 drop trigger loct_br_insert_trigger on loct;
8897 -- We can move rows to a foreign partition that has been updated already,
8898 -- but can't move rows to a foreign partition that hasn't been updated yet
8899 delete from utrtest;
8900 insert into utrtest values (1, 'foo');
8901 insert into utrtest values (2, 'qux');
8902 -- Test the former case:
8903 -- with a direct modification plan
8904 explain (verbose, costs off)
8905 update utrtest set a = 1 returning *;
8907 ---------------------------------------------------------------------------
8908 Update on public.utrtest
8909 Output: utrtest_1.a, utrtest_1.b
8910 Foreign Update on public.remp utrtest_1
8911 Update on public.locp utrtest_2
8913 -> Foreign Update on public.remp utrtest_1
8914 Remote SQL: UPDATE public.loct SET a = 1 RETURNING a, b
8915 -> Seq Scan on public.locp utrtest_2
8916 Output: 1, utrtest_2.tableoid, utrtest_2.ctid, NULL::record
8919 update utrtest set a = 1 returning *;
8920 ERROR: cannot route tuples into foreign table to be updated "remp"
8921 delete from utrtest;
8922 insert into utrtest values (1, 'foo');
8923 insert into utrtest values (2, 'qux');
8924 -- with a non-direct modification plan
8925 explain (verbose, costs off)
8926 update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *;
8928 ------------------------------------------------------------------------------------------------
8929 Update on public.utrtest
8930 Output: utrtest_1.a, utrtest_1.b, "*VALUES*".column1
8931 Foreign Update on public.remp utrtest_1
8932 Remote SQL: UPDATE public.loct SET a = $2 WHERE ctid = $1 RETURNING a, b
8933 Update on public.locp utrtest_2
8935 Output: 1, "*VALUES*".*, "*VALUES*".column1, utrtest.tableoid, utrtest.ctid, utrtest.*
8936 Hash Cond: (utrtest.a = "*VALUES*".column1)
8938 -> Foreign Scan on public.remp utrtest_1
8939 Output: utrtest_1.a, utrtest_1.tableoid, utrtest_1.ctid, utrtest_1.*
8940 Remote SQL: SELECT a, b, ctid FROM public.loct FOR UPDATE
8941 -> Seq Scan on public.locp utrtest_2
8942 Output: utrtest_2.a, utrtest_2.tableoid, utrtest_2.ctid, NULL::record
8944 Output: "*VALUES*".*, "*VALUES*".column1
8945 -> Values Scan on "*VALUES*"
8946 Output: "*VALUES*".*, "*VALUES*".column1
8949 update utrtest set a = 1 from (values (1), (2)) s(x) where a = s.x returning *;
8950 ERROR: cannot route tuples into foreign table to be updated "remp"
8951 -- Change the definition of utrtest so that the foreign partition get updated
8952 -- after the local partition
8953 delete from utrtest;
8954 alter table utrtest detach partition remp;
8955 drop foreign table remp;
8956 alter table loct drop constraint loct_a_check;
8957 alter table loct add check (a in (3));
8958 create foreign table remp (a int check (a in (3)), b text) server loopback options (table_name 'loct');
8959 alter table utrtest attach partition remp for values in (3);
8960 insert into utrtest values (2, 'qux');
8961 insert into utrtest values (3, 'xyzzy');
8962 -- Test the latter case:
8963 -- with a direct modification plan
8964 explain (verbose, costs off)
8965 update utrtest set a = 3 returning *;
8967 ---------------------------------------------------------------------------
8968 Update on public.utrtest
8969 Output: utrtest_1.a, utrtest_1.b
8970 Update on public.locp utrtest_1
8971 Foreign Update on public.remp utrtest_2
8973 -> Seq Scan on public.locp utrtest_1
8974 Output: 3, utrtest_1.tableoid, utrtest_1.ctid, NULL::record
8975 -> Foreign Update on public.remp utrtest_2
8976 Remote SQL: UPDATE public.loct SET a = 3 RETURNING a, b
8979 update utrtest set a = 3 returning *; -- ERROR
8980 ERROR: cannot route tuples into foreign table to be updated "remp"
8981 -- with a non-direct modification plan
8982 explain (verbose, costs off)
8983 update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *;
8985 -----------------------------------------------------------------------------------------------------
8986 Update on public.utrtest
8987 Output: utrtest_1.a, utrtest_1.b, "*VALUES*".column1
8988 Update on public.locp utrtest_1
8989 Foreign Update on public.remp utrtest_2
8990 Remote SQL: UPDATE public.loct SET a = $2 WHERE ctid = $1 RETURNING a, b
8992 Output: 3, "*VALUES*".*, "*VALUES*".column1, utrtest.tableoid, utrtest.ctid, (NULL::record)
8993 Hash Cond: (utrtest.a = "*VALUES*".column1)
8995 -> Seq Scan on public.locp utrtest_1
8996 Output: utrtest_1.a, utrtest_1.tableoid, utrtest_1.ctid, NULL::record
8997 -> Foreign Scan on public.remp utrtest_2
8998 Output: utrtest_2.a, utrtest_2.tableoid, utrtest_2.ctid, utrtest_2.*
8999 Remote SQL: SELECT a, b, ctid FROM public.loct FOR UPDATE
9001 Output: "*VALUES*".*, "*VALUES*".column1
9002 -> Values Scan on "*VALUES*"
9003 Output: "*VALUES*".*, "*VALUES*".column1
9006 update utrtest set a = 3 from (values (2), (3)) s(x) where a = s.x returning *; -- ERROR
9007 ERROR: cannot route tuples into foreign table to be updated "remp"
9010 -- Test copy tuple routing
9011 create table ctrtest (a int, b text) partition by list (a);
9012 create table loct1 (a int check (a in (1)), b text);
9013 create foreign table remp1 (a int check (a in (1)), b text) server loopback options (table_name 'loct1');
9014 create table loct2 (a int check (a in (2)), b text);
9015 create foreign table remp2 (b text, a int check (a in (2))) server loopback options (table_name 'loct2');
9016 alter table ctrtest attach partition remp1 for values in (1);
9017 alter table ctrtest attach partition remp2 for values in (2);
9018 copy ctrtest from stdin;
9019 select tableoid::regclass, * FROM ctrtest;
9021 ----------+---+-----
9026 select tableoid::regclass, * FROM remp1;
9028 ----------+---+-----
9032 select tableoid::regclass, * FROM remp2;
9034 ----------+-----+---
9038 -- Copying into foreign partitions directly should work as well
9039 copy remp1 from stdin;
9040 select tableoid::regclass, * FROM remp1;
9042 ----------+---+-----
9047 delete from ctrtest;
9048 -- Test copy tuple routing with the batch_size option enabled
9049 alter server loopback options (add batch_size '2');
9050 copy ctrtest from stdin;
9051 select tableoid::regclass, * FROM ctrtest;
9053 ----------+---+-------
9062 select tableoid::regclass, * FROM remp1;
9064 ----------+---+-------
9070 select tableoid::regclass, * FROM remp2;
9072 ----------+-------+---
9078 delete from ctrtest;
9079 alter server loopback options (drop batch_size);
9083 -- ===================================================================
9085 -- ===================================================================
9086 create table loc2 (f1 int, f2 text);
9087 alter table loc2 set (autovacuum_enabled = 'false');
9088 create foreign table rem2 (f1 int, f2 text) server loopback options(table_name 'loc2');
9089 -- Test basic functionality
9090 copy rem2 from stdin;
9099 -- Test check constraints
9100 alter table loc2 add constraint loc2_f1positive check (f1 >= 0);
9101 alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0);
9102 -- check constraint is enforced on the remote side, not locally
9103 copy rem2 from stdin;
9104 copy rem2 from stdin; -- ERROR
9105 ERROR: new row for relation "loc2" violates check constraint "loc2_f1positive"
9106 DETAIL: Failing row contains (-1, xyzzy).
9107 CONTEXT: remote SQL command: INSERT INTO public.loc2(f1, f2) VALUES ($1, $2)
9108 COPY rem2, line 1: "-1 xyzzy"
9116 alter foreign table rem2 drop constraint rem2_f1positive;
9117 alter table loc2 drop constraint loc2_f1positive;
9119 -- Test local triggers
9120 create trigger trig_stmt_before before insert on rem2
9121 for each statement execute procedure trigger_func();
9122 create trigger trig_stmt_after after insert on rem2
9123 for each statement execute procedure trigger_func();
9124 create trigger trig_row_before before insert on rem2
9125 for each row execute procedure trigger_data(23,'skidoo');
9126 create trigger trig_row_after after insert on rem2
9127 for each row execute procedure trigger_data(23,'skidoo');
9128 copy rem2 from stdin;
9129 NOTICE: trigger_func(<NULL>) called: action = INSERT, when = BEFORE, level = STATEMENT
9130 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem2
9131 NOTICE: NEW: (1,foo)
9132 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem2
9133 NOTICE: NEW: (2,bar)
9134 NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem2
9135 NOTICE: NEW: (1,foo)
9136 NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem2
9137 NOTICE: NEW: (2,bar)
9138 NOTICE: trigger_func(<NULL>) called: action = INSERT, when = AFTER, level = STATEMENT
9146 drop trigger trig_row_before on rem2;
9147 drop trigger trig_row_after on rem2;
9148 drop trigger trig_stmt_before on rem2;
9149 drop trigger trig_stmt_after on rem2;
9151 create trigger trig_row_before_insert before insert on rem2
9152 for each row execute procedure trig_row_before_insupdate();
9153 -- The new values are concatenated with ' triggered !'
9154 copy rem2 from stdin;
9157 ----+-----------------
9162 drop trigger trig_row_before_insert on rem2;
9164 create trigger trig_null before insert on rem2
9165 for each row execute procedure trig_null();
9167 copy rem2 from stdin;
9173 drop trigger trig_null on rem2;
9175 -- Test remote triggers
9176 create trigger trig_row_before_insert before insert on loc2
9177 for each row execute procedure trig_row_before_insupdate();
9178 -- The new values are concatenated with ' triggered !'
9179 copy rem2 from stdin;
9182 ----+-----------------
9187 drop trigger trig_row_before_insert on loc2;
9189 create trigger trig_null before insert on loc2
9190 for each row execute procedure trig_null();
9192 copy rem2 from stdin;
9198 drop trigger trig_null on loc2;
9200 -- Test a combination of local and remote triggers
9201 create trigger rem2_trig_row_before before insert on rem2
9202 for each row execute procedure trigger_data(23,'skidoo');
9203 create trigger rem2_trig_row_after after insert on rem2
9204 for each row execute procedure trigger_data(23,'skidoo');
9205 create trigger loc2_trig_row_before_insert before insert on loc2
9206 for each row execute procedure trig_row_before_insupdate();
9207 copy rem2 from stdin;
9208 NOTICE: rem2_trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem2
9209 NOTICE: NEW: (1,foo)
9210 NOTICE: rem2_trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem2
9211 NOTICE: NEW: (2,bar)
9212 NOTICE: rem2_trig_row_after(23, skidoo) AFTER ROW INSERT ON rem2
9213 NOTICE: NEW: (1,"foo triggered !")
9214 NOTICE: rem2_trig_row_after(23, skidoo) AFTER ROW INSERT ON rem2
9215 NOTICE: NEW: (2,"bar triggered !")
9218 ----+-----------------
9223 drop trigger rem2_trig_row_before on rem2;
9224 drop trigger rem2_trig_row_after on rem2;
9225 drop trigger loc2_trig_row_before_insert on loc2;
9227 -- test COPY FROM with foreign table created in the same transaction
9228 create table loc3 (f1 int, f2 text);
9230 create foreign table rem3 (f1 int, f2 text)
9231 server loopback options(table_name 'loc3');
9232 copy rem3 from stdin;
9241 drop foreign table rem3;
9243 -- Test COPY FROM with the batch_size option enabled
9244 alter server loopback options (add batch_size '2');
9245 -- Test basic functionality
9246 copy rem2 from stdin;
9256 -- Test check constraints
9257 alter table loc2 add constraint loc2_f1positive check (f1 >= 0);
9258 alter foreign table rem2 add constraint rem2_f1positive check (f1 >= 0);
9259 -- check constraint is enforced on the remote side, not locally
9260 copy rem2 from stdin;
9261 copy rem2 from stdin; -- ERROR
9262 ERROR: new row for relation "loc2" violates check constraint "loc2_f1positive"
9263 DETAIL: Failing row contains (-1, xyzzy).
9264 CONTEXT: remote SQL command: INSERT INTO public.loc2(f1, f2) VALUES ($1, $2)
9274 alter foreign table rem2 drop constraint rem2_f1positive;
9275 alter table loc2 drop constraint loc2_f1positive;
9277 -- Test remote triggers
9278 create trigger trig_row_before_insert before insert on loc2
9279 for each row execute procedure trig_row_before_insupdate();
9280 -- The new values are concatenated with ' triggered !'
9281 copy rem2 from stdin;
9284 ----+-----------------
9290 drop trigger trig_row_before_insert on loc2;
9292 create trigger trig_null before insert on loc2
9293 for each row execute procedure trig_null();
9295 copy rem2 from stdin;
9301 drop trigger trig_null on loc2;
9303 -- Check with zero-column foreign table; batch insert will be disabled
9304 alter table loc2 drop column f1;
9305 alter table loc2 drop column f2;
9306 alter table rem2 drop column f1;
9307 alter table rem2 drop column f2;
9308 copy rem2 from stdin;
9314 alter server loopback options (drop batch_size);
9315 -- ===================================================================
9316 -- test for TRUNCATE
9317 -- ===================================================================
9318 CREATE TABLE tru_rtable0 (id int primary key);
9319 CREATE FOREIGN TABLE tru_ftable (id int)
9320 SERVER loopback OPTIONS (table_name 'tru_rtable0');
9321 INSERT INTO tru_rtable0 (SELECT x FROM generate_series(1,10) x);
9322 CREATE TABLE tru_ptable (id int) PARTITION BY HASH(id);
9323 CREATE TABLE tru_ptable__p0 PARTITION OF tru_ptable
9324 FOR VALUES WITH (MODULUS 2, REMAINDER 0);
9325 CREATE TABLE tru_rtable1 (id int primary key);
9326 CREATE FOREIGN TABLE tru_ftable__p1 PARTITION OF tru_ptable
9327 FOR VALUES WITH (MODULUS 2, REMAINDER 1)
9328 SERVER loopback OPTIONS (table_name 'tru_rtable1');
9329 INSERT INTO tru_ptable (SELECT x FROM generate_series(11,20) x);
9330 CREATE TABLE tru_pk_table(id int primary key);
9331 CREATE TABLE tru_fk_table(fkey int references tru_pk_table(id));
9332 INSERT INTO tru_pk_table (SELECT x FROM generate_series(1,10) x);
9333 INSERT INTO tru_fk_table (SELECT x % 10 + 1 FROM generate_series(5,25) x);
9334 CREATE FOREIGN TABLE tru_pk_ftable (id int)
9335 SERVER loopback OPTIONS (table_name 'tru_pk_table');
9336 CREATE TABLE tru_rtable_parent (id int);
9337 CREATE TABLE tru_rtable_child (id int);
9338 CREATE FOREIGN TABLE tru_ftable_parent (id int)
9339 SERVER loopback OPTIONS (table_name 'tru_rtable_parent');
9340 CREATE FOREIGN TABLE tru_ftable_child () INHERITS (tru_ftable_parent)
9341 SERVER loopback OPTIONS (table_name 'tru_rtable_child');
9342 INSERT INTO tru_rtable_parent (SELECT x FROM generate_series(1,8) x);
9343 INSERT INTO tru_rtable_child (SELECT x FROM generate_series(10, 18) x);
9345 SELECT sum(id) FROM tru_ftable; -- 55
9351 TRUNCATE tru_ftable;
9352 SELECT count(*) FROM tru_rtable0; -- 0
9358 SELECT count(*) FROM tru_ftable; -- 0
9364 -- 'truncatable' option
9365 ALTER SERVER loopback OPTIONS (ADD truncatable 'false');
9366 TRUNCATE tru_ftable; -- error
9367 ERROR: foreign table "tru_ftable" does not allow truncates
9368 ALTER FOREIGN TABLE tru_ftable OPTIONS (ADD truncatable 'true');
9369 TRUNCATE tru_ftable; -- accepted
9370 ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'false');
9371 TRUNCATE tru_ftable; -- error
9372 ERROR: foreign table "tru_ftable" does not allow truncates
9373 ALTER SERVER loopback OPTIONS (DROP truncatable);
9374 ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'false');
9375 TRUNCATE tru_ftable; -- error
9376 ERROR: foreign table "tru_ftable" does not allow truncates
9377 ALTER FOREIGN TABLE tru_ftable OPTIONS (SET truncatable 'true');
9378 TRUNCATE tru_ftable; -- accepted
9379 -- partitioned table with both local and foreign tables as partitions
9380 SELECT sum(id) FROM tru_ptable; -- 155
9386 TRUNCATE tru_ptable;
9387 SELECT count(*) FROM tru_ptable; -- 0
9393 SELECT count(*) FROM tru_ptable__p0; -- 0
9399 SELECT count(*) FROM tru_ftable__p1; -- 0
9405 SELECT count(*) FROM tru_rtable1; -- 0
9412 SELECT sum(id) FROM tru_pk_ftable; -- 55
9418 TRUNCATE tru_pk_ftable; -- failed by FK reference
9419 ERROR: cannot truncate a table referenced in a foreign key constraint
9420 DETAIL: Table "tru_fk_table" references "tru_pk_table".
9421 HINT: Truncate table "tru_fk_table" at the same time, or use TRUNCATE ... CASCADE.
9422 CONTEXT: remote SQL command: TRUNCATE public.tru_pk_table CONTINUE IDENTITY RESTRICT
9423 TRUNCATE tru_pk_ftable CASCADE;
9424 SELECT count(*) FROM tru_pk_ftable; -- 0
9430 SELECT count(*) FROM tru_fk_table; -- also truncated,0
9436 -- truncate two tables at a command
9437 INSERT INTO tru_ftable (SELECT x FROM generate_series(1,8) x);
9438 INSERT INTO tru_pk_ftable (SELECT x FROM generate_series(3,10) x);
9439 SELECT count(*) from tru_ftable; -- 8
9445 SELECT count(*) from tru_pk_ftable; -- 8
9451 TRUNCATE tru_ftable, tru_pk_ftable CASCADE;
9452 SELECT count(*) from tru_ftable; -- 0
9458 SELECT count(*) from tru_pk_ftable; -- 0
9464 -- truncate with ONLY clause
9465 -- Since ONLY is specified, the table tru_ftable_child that inherits
9466 -- tru_ftable_parent locally is not truncated.
9467 TRUNCATE ONLY tru_ftable_parent;
9468 SELECT sum(id) FROM tru_ftable_parent; -- 126
9474 TRUNCATE tru_ftable_parent;
9475 SELECT count(*) FROM tru_ftable_parent; -- 0
9481 -- in case when remote table has inherited children
9482 CREATE TABLE tru_rtable0_child () INHERITS (tru_rtable0);
9483 INSERT INTO tru_rtable0 (SELECT x FROM generate_series(5,9) x);
9484 INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(10,14) x);
9485 SELECT sum(id) FROM tru_ftable; -- 95
9491 -- Both parent and child tables in the foreign server are truncated
9492 -- even though ONLY is specified because ONLY has no effect
9493 -- when truncating a foreign table.
9494 TRUNCATE ONLY tru_ftable;
9495 SELECT count(*) FROM tru_ftable; -- 0
9501 INSERT INTO tru_rtable0 (SELECT x FROM generate_series(21,25) x);
9502 INSERT INTO tru_rtable0_child (SELECT x FROM generate_series(26,30) x);
9503 SELECT sum(id) FROM tru_ftable; -- 255
9509 TRUNCATE tru_ftable; -- truncate both of parent and child
9510 SELECT count(*) FROM tru_ftable; -- 0
9517 DROP FOREIGN TABLE tru_ftable_parent, tru_ftable_child, tru_pk_ftable,tru_ftable__p1,tru_ftable;
9518 DROP TABLE tru_rtable0, tru_rtable1, tru_ptable, tru_ptable__p0, tru_pk_table, tru_fk_table,
9519 tru_rtable_parent,tru_rtable_child, tru_rtable0_child;
9520 -- ===================================================================
9521 -- test IMPORT FOREIGN SCHEMA
9522 -- ===================================================================
9523 CREATE SCHEMA import_source;
9524 CREATE TABLE import_source.t1 (c1 int, c2 varchar NOT NULL);
9525 CREATE TABLE import_source.t2 (c1 int default 42, c2 varchar NULL, c3 text collate "POSIX");
9526 CREATE TYPE typ1 AS (m1 int, m2 varchar);
9527 CREATE TABLE import_source.t3 (c1 timestamptz default now(), c2 typ1);
9528 CREATE TABLE import_source."x 4" (c1 float8, "C 2" text, c3 varchar(42));
9529 CREATE TABLE import_source."x 5" (c1 float8);
9530 ALTER TABLE import_source."x 5" DROP COLUMN c1;
9531 CREATE TABLE import_source."x 6" (c1 int, c2 int generated always as (c1 * 2) stored);
9532 CREATE TABLE import_source.t4 (c1 int) PARTITION BY RANGE (c1);
9533 CREATE TABLE import_source.t4_part PARTITION OF import_source.t4
9534 FOR VALUES FROM (1) TO (100);
9535 CREATE TABLE import_source.t4_part2 PARTITION OF import_source.t4
9536 FOR VALUES FROM (100) TO (200);
9537 CREATE SCHEMA import_dest1;
9538 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest1;
9539 \det+ import_dest1.*
9540 List of foreign tables
9541 Schema | Table | Server | FDW options | Description
9542 --------------+-------+----------+-------------------------------------------------+-------------
9543 import_dest1 | t1 | loopback | (schema_name 'import_source', table_name 't1') |
9544 import_dest1 | t2 | loopback | (schema_name 'import_source', table_name 't2') |
9545 import_dest1 | t3 | loopback | (schema_name 'import_source', table_name 't3') |
9546 import_dest1 | t4 | loopback | (schema_name 'import_source', table_name 't4') |
9547 import_dest1 | x 4 | loopback | (schema_name 'import_source', table_name 'x 4') |
9548 import_dest1 | x 5 | loopback | (schema_name 'import_source', table_name 'x 5') |
9549 import_dest1 | x 6 | loopback | (schema_name 'import_source', table_name 'x 6') |
9553 Foreign table "import_dest1.t1"
9554 Column | Type | Collation | Nullable | Default | FDW options
9555 --------+-------------------+-----------+----------+---------+--------------------
9556 c1 | integer | | | | (column_name 'c1')
9557 c2 | character varying | | not null | | (column_name 'c2')
9559 FDW options: (schema_name 'import_source', table_name 't1')
9561 Foreign table "import_dest1.t2"
9562 Column | Type | Collation | Nullable | Default | FDW options
9563 --------+-------------------+-----------+----------+---------+--------------------
9564 c1 | integer | | | | (column_name 'c1')
9565 c2 | character varying | | | | (column_name 'c2')
9566 c3 | text | POSIX | | | (column_name 'c3')
9568 FDW options: (schema_name 'import_source', table_name 't2')
9570 Foreign table "import_dest1.t3"
9571 Column | Type | Collation | Nullable | Default | FDW options
9572 --------+--------------------------+-----------+----------+---------+--------------------
9573 c1 | timestamp with time zone | | | | (column_name 'c1')
9574 c2 | typ1 | | | | (column_name 'c2')
9576 FDW options: (schema_name 'import_source', table_name 't3')
9578 Foreign table "import_dest1.t4"
9579 Column | Type | Collation | Nullable | Default | FDW options
9580 --------+---------+-----------+----------+---------+--------------------
9581 c1 | integer | | | | (column_name 'c1')
9583 FDW options: (schema_name 'import_source', table_name 't4')
9585 Foreign table "import_dest1.x 4"
9586 Column | Type | Collation | Nullable | Default | FDW options
9587 --------+-----------------------+-----------+----------+---------+---------------------
9588 c1 | double precision | | | | (column_name 'c1')
9589 C 2 | text | | | | (column_name 'C 2')
9590 c3 | character varying(42) | | | | (column_name 'c3')
9592 FDW options: (schema_name 'import_source', table_name 'x 4')
9594 Foreign table "import_dest1.x 5"
9595 Column | Type | Collation | Nullable | Default | FDW options
9596 --------+------+-----------+----------+---------+-------------
9598 FDW options: (schema_name 'import_source', table_name 'x 5')
9600 Foreign table "import_dest1.x 6"
9601 Column | Type | Collation | Nullable | Default | FDW options
9602 --------+---------+-----------+----------+-------------------------------------+--------------------
9603 c1 | integer | | | | (column_name 'c1')
9604 c2 | integer | | | generated always as (c1 * 2) stored | (column_name 'c2')
9606 FDW options: (schema_name 'import_source', table_name 'x 6')
9609 CREATE SCHEMA import_dest2;
9610 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest2
9611 OPTIONS (import_default 'true');
9612 \det+ import_dest2.*
9613 List of foreign tables
9614 Schema | Table | Server | FDW options | Description
9615 --------------+-------+----------+-------------------------------------------------+-------------
9616 import_dest2 | t1 | loopback | (schema_name 'import_source', table_name 't1') |
9617 import_dest2 | t2 | loopback | (schema_name 'import_source', table_name 't2') |
9618 import_dest2 | t3 | loopback | (schema_name 'import_source', table_name 't3') |
9619 import_dest2 | t4 | loopback | (schema_name 'import_source', table_name 't4') |
9620 import_dest2 | x 4 | loopback | (schema_name 'import_source', table_name 'x 4') |
9621 import_dest2 | x 5 | loopback | (schema_name 'import_source', table_name 'x 5') |
9622 import_dest2 | x 6 | loopback | (schema_name 'import_source', table_name 'x 6') |
9626 Foreign table "import_dest2.t1"
9627 Column | Type | Collation | Nullable | Default | FDW options
9628 --------+-------------------+-----------+----------+---------+--------------------
9629 c1 | integer | | | | (column_name 'c1')
9630 c2 | character varying | | not null | | (column_name 'c2')
9632 FDW options: (schema_name 'import_source', table_name 't1')
9634 Foreign table "import_dest2.t2"
9635 Column | Type | Collation | Nullable | Default | FDW options
9636 --------+-------------------+-----------+----------+---------+--------------------
9637 c1 | integer | | | 42 | (column_name 'c1')
9638 c2 | character varying | | | | (column_name 'c2')
9639 c3 | text | POSIX | | | (column_name 'c3')
9641 FDW options: (schema_name 'import_source', table_name 't2')
9643 Foreign table "import_dest2.t3"
9644 Column | Type | Collation | Nullable | Default | FDW options
9645 --------+--------------------------+-----------+----------+---------+--------------------
9646 c1 | timestamp with time zone | | | now() | (column_name 'c1')
9647 c2 | typ1 | | | | (column_name 'c2')
9649 FDW options: (schema_name 'import_source', table_name 't3')
9651 Foreign table "import_dest2.t4"
9652 Column | Type | Collation | Nullable | Default | FDW options
9653 --------+---------+-----------+----------+---------+--------------------
9654 c1 | integer | | | | (column_name 'c1')
9656 FDW options: (schema_name 'import_source', table_name 't4')
9658 Foreign table "import_dest2.x 4"
9659 Column | Type | Collation | Nullable | Default | FDW options
9660 --------+-----------------------+-----------+----------+---------+---------------------
9661 c1 | double precision | | | | (column_name 'c1')
9662 C 2 | text | | | | (column_name 'C 2')
9663 c3 | character varying(42) | | | | (column_name 'c3')
9665 FDW options: (schema_name 'import_source', table_name 'x 4')
9667 Foreign table "import_dest2.x 5"
9668 Column | Type | Collation | Nullable | Default | FDW options
9669 --------+------+-----------+----------+---------+-------------
9671 FDW options: (schema_name 'import_source', table_name 'x 5')
9673 Foreign table "import_dest2.x 6"
9674 Column | Type | Collation | Nullable | Default | FDW options
9675 --------+---------+-----------+----------+-------------------------------------+--------------------
9676 c1 | integer | | | | (column_name 'c1')
9677 c2 | integer | | | generated always as (c1 * 2) stored | (column_name 'c2')
9679 FDW options: (schema_name 'import_source', table_name 'x 6')
9681 CREATE SCHEMA import_dest3;
9682 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest3
9683 OPTIONS (import_collate 'false', import_generated 'false', import_not_null 'false');
9684 \det+ import_dest3.*
9685 List of foreign tables
9686 Schema | Table | Server | FDW options | Description
9687 --------------+-------+----------+-------------------------------------------------+-------------
9688 import_dest3 | t1 | loopback | (schema_name 'import_source', table_name 't1') |
9689 import_dest3 | t2 | loopback | (schema_name 'import_source', table_name 't2') |
9690 import_dest3 | t3 | loopback | (schema_name 'import_source', table_name 't3') |
9691 import_dest3 | t4 | loopback | (schema_name 'import_source', table_name 't4') |
9692 import_dest3 | x 4 | loopback | (schema_name 'import_source', table_name 'x 4') |
9693 import_dest3 | x 5 | loopback | (schema_name 'import_source', table_name 'x 5') |
9694 import_dest3 | x 6 | loopback | (schema_name 'import_source', table_name 'x 6') |
9698 Foreign table "import_dest3.t1"
9699 Column | Type | Collation | Nullable | Default | FDW options
9700 --------+-------------------+-----------+----------+---------+--------------------
9701 c1 | integer | | | | (column_name 'c1')
9702 c2 | character varying | | | | (column_name 'c2')
9704 FDW options: (schema_name 'import_source', table_name 't1')
9706 Foreign table "import_dest3.t2"
9707 Column | Type | Collation | Nullable | Default | FDW options
9708 --------+-------------------+-----------+----------+---------+--------------------
9709 c1 | integer | | | | (column_name 'c1')
9710 c2 | character varying | | | | (column_name 'c2')
9711 c3 | text | | | | (column_name 'c3')
9713 FDW options: (schema_name 'import_source', table_name 't2')
9715 Foreign table "import_dest3.t3"
9716 Column | Type | Collation | Nullable | Default | FDW options
9717 --------+--------------------------+-----------+----------+---------+--------------------
9718 c1 | timestamp with time zone | | | | (column_name 'c1')
9719 c2 | typ1 | | | | (column_name 'c2')
9721 FDW options: (schema_name 'import_source', table_name 't3')
9723 Foreign table "import_dest3.t4"
9724 Column | Type | Collation | Nullable | Default | FDW options
9725 --------+---------+-----------+----------+---------+--------------------
9726 c1 | integer | | | | (column_name 'c1')
9728 FDW options: (schema_name 'import_source', table_name 't4')
9730 Foreign table "import_dest3.x 4"
9731 Column | Type | Collation | Nullable | Default | FDW options
9732 --------+-----------------------+-----------+----------+---------+---------------------
9733 c1 | double precision | | | | (column_name 'c1')
9734 C 2 | text | | | | (column_name 'C 2')
9735 c3 | character varying(42) | | | | (column_name 'c3')
9737 FDW options: (schema_name 'import_source', table_name 'x 4')
9739 Foreign table "import_dest3.x 5"
9740 Column | Type | Collation | Nullable | Default | FDW options
9741 --------+------+-----------+----------+---------+-------------
9743 FDW options: (schema_name 'import_source', table_name 'x 5')
9745 Foreign table "import_dest3.x 6"
9746 Column | Type | Collation | Nullable | Default | FDW options
9747 --------+---------+-----------+----------+---------+--------------------
9748 c1 | integer | | | | (column_name 'c1')
9749 c2 | integer | | | | (column_name 'c2')
9751 FDW options: (schema_name 'import_source', table_name 'x 6')
9753 -- Check LIMIT TO and EXCEPT
9754 CREATE SCHEMA import_dest4;
9755 IMPORT FOREIGN SCHEMA import_source LIMIT TO (t1, nonesuch, t4_part)
9756 FROM SERVER loopback INTO import_dest4;
9757 \det+ import_dest4.*
9758 List of foreign tables
9759 Schema | Table | Server | FDW options | Description
9760 --------------+---------+----------+-----------------------------------------------------+-------------
9761 import_dest4 | t1 | loopback | (schema_name 'import_source', table_name 't1') |
9762 import_dest4 | t4_part | loopback | (schema_name 'import_source', table_name 't4_part') |
9765 IMPORT FOREIGN SCHEMA import_source EXCEPT (t1, "x 4", nonesuch, t4_part)
9766 FROM SERVER loopback INTO import_dest4;
9767 \det+ import_dest4.*
9768 List of foreign tables
9769 Schema | Table | Server | FDW options | Description
9770 --------------+---------+----------+-----------------------------------------------------+-------------
9771 import_dest4 | t1 | loopback | (schema_name 'import_source', table_name 't1') |
9772 import_dest4 | t2 | loopback | (schema_name 'import_source', table_name 't2') |
9773 import_dest4 | t3 | loopback | (schema_name 'import_source', table_name 't3') |
9774 import_dest4 | t4 | loopback | (schema_name 'import_source', table_name 't4') |
9775 import_dest4 | t4_part | loopback | (schema_name 'import_source', table_name 't4_part') |
9776 import_dest4 | x 5 | loopback | (schema_name 'import_source', table_name 'x 5') |
9777 import_dest4 | x 6 | loopback | (schema_name 'import_source', table_name 'x 6') |
9780 -- Assorted error cases
9781 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest4;
9782 ERROR: relation "t1" already exists
9783 CONTEXT: importing foreign table "t1"
9784 IMPORT FOREIGN SCHEMA nonesuch FROM SERVER loopback INTO import_dest4;
9785 ERROR: schema "nonesuch" is not present on foreign server "loopback"
9786 IMPORT FOREIGN SCHEMA nonesuch FROM SERVER loopback INTO notthere;
9787 ERROR: schema "notthere" does not exist
9788 IMPORT FOREIGN SCHEMA nonesuch FROM SERVER nowhere INTO notthere;
9789 ERROR: server "nowhere" does not exist
9790 -- Check case of a type present only on the remote server.
9791 -- We can fake this by dropping the type locally in our transaction.
9792 CREATE TYPE "Colors" AS ENUM ('red', 'green', 'blue');
9793 CREATE TABLE import_source.t5 (c1 int, c2 text collate "C", "Col" "Colors");
9794 CREATE SCHEMA import_dest5;
9796 DROP TYPE "Colors" CASCADE;
9797 NOTICE: drop cascades to column Col of table import_source.t5
9798 IMPORT FOREIGN SCHEMA import_source LIMIT TO (t5)
9799 FROM SERVER loopback INTO import_dest5; -- ERROR
9800 ERROR: type "public.Colors" does not exist
9801 LINE 4: "Col" public."Colors" OPTIONS (column_name 'Col')
9803 QUERY: CREATE FOREIGN TABLE t5 (
9804 c1 integer OPTIONS (column_name 'c1'),
9805 c2 text OPTIONS (column_name 'c2') COLLATE pg_catalog."C",
9806 "Col" public."Colors" OPTIONS (column_name 'Col')
9808 OPTIONS (schema_name 'import_source', table_name 't5');
9809 CONTEXT: importing foreign table "t5"
9812 CREATE SERVER fetch101 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( fetch_size '101' );
9814 FROM pg_foreign_server
9815 WHERE srvname = 'fetch101'
9816 AND srvoptions @> array['fetch_size=101'];
9822 ALTER SERVER fetch101 OPTIONS( SET fetch_size '202' );
9824 FROM pg_foreign_server
9825 WHERE srvname = 'fetch101'
9826 AND srvoptions @> array['fetch_size=101'];
9833 FROM pg_foreign_server
9834 WHERE srvname = 'fetch101'
9835 AND srvoptions @> array['fetch_size=202'];
9841 CREATE FOREIGN TABLE table30000 ( x int ) SERVER fetch101 OPTIONS ( fetch_size '30000' );
9843 FROM pg_foreign_table
9844 WHERE ftrelid = 'table30000'::regclass
9845 AND ftoptions @> array['fetch_size=30000'];
9851 ALTER FOREIGN TABLE table30000 OPTIONS ( SET fetch_size '60000');
9853 FROM pg_foreign_table
9854 WHERE ftrelid = 'table30000'::regclass
9855 AND ftoptions @> array['fetch_size=30000'];
9862 FROM pg_foreign_table
9863 WHERE ftrelid = 'table30000'::regclass
9864 AND ftoptions @> array['fetch_size=60000'];
9871 -- ===================================================================
9872 -- test partitionwise joins
9873 -- ===================================================================
9874 SET enable_partitionwise_join=on;
9875 CREATE TABLE fprt1 (a int, b int, c varchar) PARTITION BY RANGE(a);
9876 CREATE TABLE fprt1_p1 (LIKE fprt1);
9877 CREATE TABLE fprt1_p2 (LIKE fprt1);
9878 ALTER TABLE fprt1_p1 SET (autovacuum_enabled = 'false');
9879 ALTER TABLE fprt1_p2 SET (autovacuum_enabled = 'false');
9880 INSERT INTO fprt1_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 2) i;
9881 INSERT INTO fprt1_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 2) i;
9882 CREATE FOREIGN TABLE ftprt1_p1 PARTITION OF fprt1 FOR VALUES FROM (0) TO (250)
9883 SERVER loopback OPTIONS (table_name 'fprt1_p1', use_remote_estimate 'true');
9884 CREATE FOREIGN TABLE ftprt1_p2 PARTITION OF fprt1 FOR VALUES FROM (250) TO (500)
9885 SERVER loopback OPTIONS (TABLE_NAME 'fprt1_p2');
9889 CREATE TABLE fprt2 (a int, b int, c varchar) PARTITION BY RANGE(b);
9890 CREATE TABLE fprt2_p1 (LIKE fprt2);
9891 CREATE TABLE fprt2_p2 (LIKE fprt2);
9892 ALTER TABLE fprt2_p1 SET (autovacuum_enabled = 'false');
9893 ALTER TABLE fprt2_p2 SET (autovacuum_enabled = 'false');
9894 INSERT INTO fprt2_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 3) i;
9895 INSERT INTO fprt2_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 3) i;
9896 CREATE FOREIGN TABLE ftprt2_p1 (b int, c varchar, a int)
9897 SERVER loopback OPTIONS (table_name 'fprt2_p1', use_remote_estimate 'true');
9898 ALTER TABLE fprt2 ATTACH PARTITION ftprt2_p1 FOR VALUES FROM (0) TO (250);
9899 CREATE FOREIGN TABLE ftprt2_p2 PARTITION OF fprt2 FOR VALUES FROM (250) TO (500)
9900 SERVER loopback OPTIONS (table_name 'fprt2_p2', use_remote_estimate 'true');
9904 -- inner join three tables
9906 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;
9908 -----------------------------------------------------------------------------------------------------
9910 Sort Key: t1.a, t3.c
9913 Relations: ((ftprt1_p1 t1_1) INNER JOIN (ftprt2_p1 t2_1)) INNER JOIN (ftprt1_p1 t3_1)
9915 Relations: ((ftprt1_p2 t1_2) INNER JOIN (ftprt2_p2 t2_2)) INNER JOIN (ftprt1_p2 t3_2)
9918 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;
9927 -- left outer join + nullable clause
9928 EXPLAIN (VERBOSE, COSTS OFF)
9929 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;
9931 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
9933 Output: t1.a, fprt2.b, fprt2.c
9934 Relations: (public.ftprt1_p1 t1) LEFT JOIN (public.ftprt2_p1 fprt2)
9935 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
9938 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;
9948 -- with whole-row reference; partitionwise join does not apply
9950 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;
9952 --------------------------------------------------------
9954 Sort Key: ((t1.*)::fprt1), ((t2.*)::fprt2)
9956 Hash Cond: (t1.a = t2.b)
9958 -> Foreign Scan on ftprt1_p1 t1_1
9959 -> Foreign Scan on ftprt1_p2 t1_2
9962 -> Foreign Scan on ftprt2_p1 t2_1
9963 -> Foreign Scan on ftprt2_p2 t2_2
9966 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;
9968 ----------------+----------------
9969 (0,0,0000) | (0,0,0000)
9972 (150,150,0003) | (150,150,0003)
9974 (250,250,0005) | (250,250,0005)
9977 (400,400,0008) | (400,400,0008)
9985 -- join with lateral reference
9987 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;
9989 -----------------------------------------------------------------------
9991 Sort Key: t1.a, t1.b
9994 Relations: (ftprt1_p1 t1_1) INNER JOIN (ftprt2_p1 t2_1)
9996 Relations: (ftprt1_p2 t1_2) INNER JOIN (ftprt2_p2 t2_2)
9999 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;
10008 -- with PHVs, partitionwise join selected but no join pushdown
10009 EXPLAIN (COSTS OFF)
10010 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;
10012 -----------------------------------------------------------
10014 Sort Key: fprt1.a, fprt2.b
10017 Hash Cond: (fprt1_1.a = fprt2_1.b)
10018 -> Foreign Scan on ftprt1_p1 fprt1_1
10020 -> Foreign Scan on ftprt2_p1 fprt2_1
10022 Hash Cond: (fprt1_2.a = fprt2_2.b)
10023 -> Foreign Scan on ftprt1_p2 fprt1_2
10025 -> Foreign Scan on ftprt2_p2 fprt2_2
10028 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;
10030 -----+--------+-----+--------
10031 0 | t1_phv | 0 | t2_phv
10034 150 | t1_phv | 150 | t2_phv
10036 250 | t1_phv | 250 | t2_phv
10039 400 | t1_phv | 400 | t2_phv
10047 -- test FOR UPDATE; partitionwise join does not apply
10048 EXPLAIN (COSTS OFF)
10049 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;
10051 --------------------------------------------------------
10054 Join Filter: (t1.a = t2.b)
10056 -> Foreign Scan on ftprt1_p1 t1_1
10057 -> Foreign Scan on ftprt1_p2 t1_2
10060 -> Foreign Scan on ftprt2_p1 t2_1
10061 -> Foreign Scan on ftprt2_p2 t2_2
10064 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;
10073 RESET enable_partitionwise_join;
10074 -- ===================================================================
10075 -- test partitionwise aggregates
10076 -- ===================================================================
10077 CREATE TABLE pagg_tab (a int, b int, c text) PARTITION BY RANGE(a);
10078 CREATE TABLE pagg_tab_p1 (LIKE pagg_tab);
10079 CREATE TABLE pagg_tab_p2 (LIKE pagg_tab);
10080 CREATE TABLE pagg_tab_p3 (LIKE pagg_tab);
10081 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;
10082 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;
10083 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;
10084 -- Create foreign partitions
10085 CREATE FOREIGN TABLE fpagg_tab_p1 PARTITION OF pagg_tab FOR VALUES FROM (0) TO (10) SERVER loopback OPTIONS (table_name 'pagg_tab_p1');
10086 CREATE FOREIGN TABLE fpagg_tab_p2 PARTITION OF pagg_tab FOR VALUES FROM (10) TO (20) SERVER loopback OPTIONS (table_name 'pagg_tab_p2');
10087 CREATE FOREIGN TABLE fpagg_tab_p3 PARTITION OF pagg_tab FOR VALUES FROM (20) TO (30) SERVER loopback OPTIONS (table_name 'pagg_tab_p3');
10089 ANALYZE fpagg_tab_p1;
10090 ANALYZE fpagg_tab_p2;
10091 ANALYZE fpagg_tab_p3;
10092 -- When GROUP BY clause matches with PARTITION KEY.
10093 -- Plan with partitionwise aggregates is disabled
10094 SET enable_partitionwise_aggregate TO false;
10095 EXPLAIN (COSTS OFF)
10096 SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1;
10098 -----------------------------------------------------
10100 Group Key: pagg_tab.a
10101 Filter: (avg(pagg_tab.b) < '22'::numeric)
10103 -> Foreign Scan on fpagg_tab_p1 pagg_tab_1
10104 -> Foreign Scan on fpagg_tab_p2 pagg_tab_2
10105 -> Foreign Scan on fpagg_tab_p3 pagg_tab_3
10108 -- Plan with partitionwise aggregates is enabled
10109 SET enable_partitionwise_aggregate TO true;
10110 EXPLAIN (COSTS OFF)
10111 SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1;
10113 -----------------------------------------------------------------
10115 Sort Key: pagg_tab.a
10118 Relations: Aggregate on (fpagg_tab_p1 pagg_tab)
10120 Relations: Aggregate on (fpagg_tab_p2 pagg_tab_1)
10122 Relations: Aggregate on (fpagg_tab_p3 pagg_tab_2)
10125 SELECT a, sum(b), min(b), count(*) FROM pagg_tab GROUP BY a HAVING avg(b) < 22 ORDER BY 1;
10126 a | sum | min | count
10127 ----+------+-----+-------
10130 10 | 2000 | 0 | 100
10131 11 | 2100 | 1 | 100
10132 20 | 2000 | 0 | 100
10133 21 | 2100 | 1 | 100
10136 -- Check with whole-row reference
10137 -- Should have all the columns in the target list for the given relation
10138 EXPLAIN (VERBOSE, COSTS OFF)
10139 SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1;
10141 --------------------------------------------------------------------------------------------
10145 Output: t1.a, count(((t1.*)::pagg_tab))
10147 Filter: (avg(t1.b) < '22'::numeric)
10148 -> Foreign Scan on public.fpagg_tab_p1 t1
10149 Output: t1.a, t1.*, t1.b
10150 Remote SQL: SELECT a, b, c FROM public.pagg_tab_p1 ORDER BY a ASC NULLS LAST
10152 Output: t1_1.a, count(((t1_1.*)::pagg_tab))
10154 Filter: (avg(t1_1.b) < '22'::numeric)
10155 -> Foreign Scan on public.fpagg_tab_p2 t1_1
10156 Output: t1_1.a, t1_1.*, t1_1.b
10157 Remote SQL: SELECT a, b, c FROM public.pagg_tab_p2 ORDER BY a ASC NULLS LAST
10159 Output: t1_2.a, count(((t1_2.*)::pagg_tab))
10161 Filter: (avg(t1_2.b) < '22'::numeric)
10162 -> Foreign Scan on public.fpagg_tab_p3 t1_2
10163 Output: t1_2.a, t1_2.*, t1_2.b
10164 Remote SQL: SELECT a, b, c FROM public.pagg_tab_p3 ORDER BY a ASC NULLS LAST
10167 SELECT a, count(t1) FROM pagg_tab t1 GROUP BY a HAVING avg(b) < 22 ORDER BY 1;
10178 -- When GROUP BY clause does not match with PARTITION KEY.
10179 EXPLAIN (COSTS OFF)
10180 SELECT b, avg(a), max(a), count(*) FROM pagg_tab GROUP BY b HAVING sum(a) < 700 ORDER BY 1;
10182 -----------------------------------------------------------
10183 Finalize GroupAggregate
10184 Group Key: pagg_tab.b
10185 Filter: (sum(pagg_tab.a) < 700)
10187 Sort Key: pagg_tab.b
10188 -> Partial GroupAggregate
10189 Group Key: pagg_tab.b
10190 -> Foreign Scan on fpagg_tab_p1 pagg_tab
10191 -> Partial GroupAggregate
10192 Group Key: pagg_tab_1.b
10193 -> Foreign Scan on fpagg_tab_p2 pagg_tab_1
10194 -> Partial GroupAggregate
10195 Group Key: pagg_tab_2.b
10196 -> Foreign Scan on fpagg_tab_p3 pagg_tab_2
10199 -- ===================================================================
10200 -- access rights and superuser
10201 -- ===================================================================
10202 -- Non-superuser cannot create a FDW without a password in the connstr
10203 CREATE ROLE regress_nosuper NOSUPERUSER;
10204 GRANT USAGE ON FOREIGN DATA WRAPPER postgres_fdw TO regress_nosuper;
10205 SET ROLE regress_nosuper;
10212 -- This will be OK, we can create the FDW
10215 EXECUTE $$CREATE SERVER loopback_nopw FOREIGN DATA WRAPPER postgres_fdw
10216 OPTIONS (dbname '$$||current_database()||$$',
10217 port '$$||current_setting('port')||$$'
10221 -- But creation of user mappings for non-superusers should fail
10222 CREATE USER MAPPING FOR public SERVER loopback_nopw;
10223 CREATE USER MAPPING FOR CURRENT_USER SERVER loopback_nopw;
10224 CREATE FOREIGN TABLE pg_temp.ft1_nopw (
10231 c7 char(10) default 'ft1',
10233 ) SERVER loopback_nopw OPTIONS (schema_name 'public', table_name 'ft1');
10234 SELECT 1 FROM ft1_nopw LIMIT 1;
10235 ERROR: password or GSSAPI delegated credentials required
10236 DETAIL: Non-superusers must delegate GSSAPI credentials or provide a password in the user mapping.
10237 -- If we add a password to the connstr it'll fail, because we don't allow passwords
10238 -- in connstrs only in user mappings.
10239 ALTER SERVER loopback_nopw OPTIONS (ADD password 'dummypw');
10240 ERROR: invalid option "password"
10241 HINT: Perhaps you meant the option "passfile".
10242 -- If we add a password for our user mapping instead, we should get a different
10243 -- error because the password wasn't actually *used* when we run with trust auth.
10245 -- This won't work with installcheck, but neither will most of the FDW checks.
10246 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback_nopw OPTIONS (ADD password 'dummypw');
10247 SELECT 1 FROM ft1_nopw LIMIT 1;
10248 ERROR: password or GSSAPI delegated credentials required
10249 DETAIL: Non-superuser cannot connect if the server does not request a password or use GSSAPI with delegated credentials.
10250 HINT: Target server's authentication method must be changed or password_required=false set in the user mapping attributes.
10251 -- Unpriv user cannot make the mapping passwordless
10252 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback_nopw OPTIONS (ADD password_required 'false');
10253 ERROR: password_required=false is superuser-only
10254 HINT: User mappings with the password_required option set to false may only be created or modified by the superuser.
10255 SELECT 1 FROM ft1_nopw LIMIT 1;
10256 ERROR: password or GSSAPI delegated credentials required
10257 DETAIL: Non-superuser cannot connect if the server does not request a password or use GSSAPI with delegated credentials.
10258 HINT: Target server's authentication method must be changed or password_required=false set in the user mapping attributes.
10260 -- But the superuser can
10261 ALTER USER MAPPING FOR regress_nosuper SERVER loopback_nopw OPTIONS (ADD password_required 'false');
10262 SET ROLE regress_nosuper;
10263 -- Should finally work now
10264 SELECT 1 FROM ft1_nopw LIMIT 1;
10270 -- unpriv user also cannot set sslcert / sslkey on the user mapping
10271 -- first set password_required so we see the right error messages
10272 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback_nopw OPTIONS (SET password_required 'true');
10273 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback_nopw OPTIONS (ADD sslcert 'foo.crt');
10274 ERROR: sslcert and sslkey are superuser-only
10275 HINT: User mappings with the sslcert or sslkey options set may only be created or modified by the superuser.
10276 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback_nopw OPTIONS (ADD sslkey 'foo.key');
10277 ERROR: sslcert and sslkey are superuser-only
10278 HINT: User mappings with the sslcert or sslkey options set may only be created or modified by the superuser.
10279 -- We're done with the role named after a specific user and need to check the
10280 -- changes to the public mapping.
10281 DROP USER MAPPING FOR CURRENT_USER SERVER loopback_nopw;
10282 -- This will fail again as it'll resolve the user mapping for public, which
10283 -- lacks password_required=false
10284 SELECT 1 FROM ft1_nopw LIMIT 1;
10285 ERROR: password or GSSAPI delegated credentials required
10286 DETAIL: Non-superusers must delegate GSSAPI credentials or provide a password in the user mapping.
10288 -- The user mapping for public is passwordless and lacks the password_required=false
10289 -- mapping option, but will work because the current user is a superuser.
10290 SELECT 1 FROM ft1_nopw LIMIT 1;
10297 DROP USER MAPPING FOR public SERVER loopback_nopw;
10298 DROP OWNED BY regress_nosuper;
10299 DROP ROLE regress_nosuper;
10301 RESET enable_partitionwise_aggregate;
10302 -- Two-phase transactions are not supported.
10304 SELECT count(*) FROM ft1;
10311 PREPARE TRANSACTION 'fdw_tpc';
10312 ERROR: cannot PREPARE a transaction that has operated on postgres_fdw foreign tables
10314 WARNING: there is no transaction in progress
10315 -- ===================================================================
10316 -- reestablish new connection
10317 -- ===================================================================
10318 -- Change application_name of remote connection to special one
10319 -- so that we can easily terminate the connection later.
10320 ALTER SERVER loopback OPTIONS (application_name 'fdw_retry_check');
10321 -- Make sure we have a remote connection.
10322 SELECT 1 FROM ft1 LIMIT 1;
10328 -- Terminate the remote connection and wait for the termination to complete.
10329 -- (If a cache flush happens, the remote connection might have already been
10330 -- dropped; so code this step in a way that doesn't fail if no connection.)
10332 PERFORM pg_terminate_backend(pid, 180000) FROM pg_stat_activity
10333 WHERE application_name = 'fdw_retry_check';
10335 -- This query should detect the broken connection when starting new remote
10336 -- transaction, reestablish new connection, and then succeed.
10338 SELECT 1 FROM ft1 LIMIT 1;
10344 -- If we detect the broken connection when starting a new remote
10345 -- subtransaction, we should fail instead of establishing a new connection.
10346 -- Terminate the remote connection and wait for the termination to complete.
10348 PERFORM pg_terminate_backend(pid, 180000) FROM pg_stat_activity
10349 WHERE application_name = 'fdw_retry_check';
10352 -- The text of the error might vary across platforms, so only show SQLSTATE.
10353 \set VERBOSITY sqlstate
10354 SELECT 1 FROM ft1 LIMIT 1; -- should fail
10356 \set VERBOSITY default
10358 -- =============================================================================
10359 -- test connection invalidation cases and postgres_fdw_get_connections function
10360 -- =============================================================================
10361 -- Let's ensure to close all the existing cached connections.
10362 SELECT 1 FROM postgres_fdw_disconnect_all();
10368 -- No cached connections, so no records should be output.
10369 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10374 -- This test case is for closing the connection in pgfdw_xact_callback
10376 -- Connection xact depth becomes 1 i.e. the connection is in midst of the xact.
10377 SELECT 1 FROM ft1 LIMIT 1;
10383 SELECT 1 FROM ft7 LIMIT 1;
10389 -- List all the existing cached connections. loopback and loopback3 should be
10391 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10398 -- Connections are not closed at the end of the alter and drop statements.
10399 -- That's because the connections are in midst of this xact,
10400 -- they are just marked as invalid in pgfdw_inval_callback.
10401 ALTER SERVER loopback OPTIONS (ADD use_remote_estimate 'off');
10402 DROP SERVER loopback3 CASCADE;
10403 NOTICE: drop cascades to 2 other objects
10404 DETAIL: drop cascades to user mapping for public on server loopback3
10405 drop cascades to foreign table ft7
10406 -- List all the existing cached connections. loopback and loopback3
10407 -- should be output as invalid connections. Also the server name for
10408 -- loopback3 should be NULL because the server was dropped.
10409 SELECT * FROM postgres_fdw_get_connections() ORDER BY 1;
10410 server_name | valid
10411 -------------+-------
10416 -- The invalid connections get closed in pgfdw_xact_callback during commit.
10418 -- All cached connections were closed while committing above xact, so no
10419 -- records should be output.
10420 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10425 -- =======================================================================
10426 -- test postgres_fdw_disconnect and postgres_fdw_disconnect_all functions
10427 -- =======================================================================
10429 -- Ensure to cache loopback connection.
10430 SELECT 1 FROM ft1 LIMIT 1;
10436 -- Ensure to cache loopback2 connection.
10437 SELECT 1 FROM ft6 LIMIT 1;
10443 -- List all the existing cached connections. loopback and loopback2 should be
10445 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10452 -- Issue a warning and return false as loopback connection is still in use and
10453 -- can not be closed.
10454 SELECT postgres_fdw_disconnect('loopback');
10455 WARNING: cannot close connection for server "loopback" because it is still in use
10456 postgres_fdw_disconnect
10457 -------------------------
10461 -- List all the existing cached connections. loopback and loopback2 should be
10463 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10470 -- Return false as connections are still in use, warnings are issued.
10471 -- But disable warnings temporarily because the order of them is not stable.
10472 SET client_min_messages = 'ERROR';
10473 SELECT postgres_fdw_disconnect_all();
10474 postgres_fdw_disconnect_all
10475 -----------------------------
10479 RESET client_min_messages;
10481 -- Ensure that loopback2 connection is closed.
10482 SELECT 1 FROM postgres_fdw_disconnect('loopback2');
10488 SELECT server_name FROM postgres_fdw_get_connections() WHERE server_name = 'loopback2';
10493 -- Return false as loopback2 connection is closed already.
10494 SELECT postgres_fdw_disconnect('loopback2');
10495 postgres_fdw_disconnect
10496 -------------------------
10500 -- Return an error as there is no foreign server with given name.
10501 SELECT postgres_fdw_disconnect('unknownserver');
10502 ERROR: server "unknownserver" does not exist
10503 -- Let's ensure to close all the existing cached connections.
10504 SELECT 1 FROM postgres_fdw_disconnect_all();
10510 -- No cached connections, so no records should be output.
10511 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10516 -- =============================================================================
10517 -- test case for having multiple cached connections for a foreign server
10518 -- =============================================================================
10519 CREATE ROLE regress_multi_conn_user1 SUPERUSER;
10520 CREATE ROLE regress_multi_conn_user2 SUPERUSER;
10521 CREATE USER MAPPING FOR regress_multi_conn_user1 SERVER loopback;
10522 CREATE USER MAPPING FOR regress_multi_conn_user2 SERVER loopback;
10524 -- Will cache loopback connection with user mapping for regress_multi_conn_user1
10525 SET ROLE regress_multi_conn_user1;
10526 SELECT 1 FROM ft1 LIMIT 1;
10533 -- Will cache loopback connection with user mapping for regress_multi_conn_user2
10534 SET ROLE regress_multi_conn_user2;
10535 SELECT 1 FROM ft1 LIMIT 1;
10542 -- Should output two connections for loopback server
10543 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10551 -- Let's ensure to close all the existing cached connections.
10552 SELECT 1 FROM postgres_fdw_disconnect_all();
10558 -- No cached connections, so no records should be output.
10559 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10565 DROP USER MAPPING FOR regress_multi_conn_user1 SERVER loopback;
10566 DROP USER MAPPING FOR regress_multi_conn_user2 SERVER loopback;
10567 DROP ROLE regress_multi_conn_user1;
10568 DROP ROLE regress_multi_conn_user2;
10569 -- ===================================================================
10570 -- Test foreign server level option keep_connections
10571 -- ===================================================================
10572 -- By default, the connections associated with foreign server are cached i.e.
10573 -- keep_connections option is on. Set it to off.
10574 ALTER SERVER loopback OPTIONS (keep_connections 'off');
10575 -- connection to loopback server is closed at the end of xact
10576 -- as keep_connections was set to off.
10577 SELECT 1 FROM ft1 LIMIT 1;
10583 -- No cached connections, so no records should be output.
10584 SELECT server_name FROM postgres_fdw_get_connections() ORDER BY 1;
10589 ALTER SERVER loopback OPTIONS (SET keep_connections 'on');
10590 -- ===================================================================
10592 -- ===================================================================
10594 CREATE SERVER batch10 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( batch_size '10' );
10596 FROM pg_foreign_server
10597 WHERE srvname = 'batch10'
10598 AND srvoptions @> array['batch_size=10'];
10604 ALTER SERVER batch10 OPTIONS( SET batch_size '20' );
10606 FROM pg_foreign_server
10607 WHERE srvname = 'batch10'
10608 AND srvoptions @> array['batch_size=10'];
10615 FROM pg_foreign_server
10616 WHERE srvname = 'batch10'
10617 AND srvoptions @> array['batch_size=20'];
10623 CREATE FOREIGN TABLE table30 ( x int ) SERVER batch10 OPTIONS ( batch_size '30' );
10625 FROM pg_foreign_table
10626 WHERE ftrelid = 'table30'::regclass
10627 AND ftoptions @> array['batch_size=30'];
10633 ALTER FOREIGN TABLE table30 OPTIONS ( SET batch_size '40');
10635 FROM pg_foreign_table
10636 WHERE ftrelid = 'table30'::regclass
10637 AND ftoptions @> array['batch_size=30'];
10644 FROM pg_foreign_table
10645 WHERE ftrelid = 'table30'::regclass
10646 AND ftoptions @> array['batch_size=40'];
10653 CREATE TABLE batch_table ( x int );
10654 CREATE FOREIGN TABLE ftable ( x int ) SERVER loopback OPTIONS ( table_name 'batch_table', batch_size '10' );
10655 EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable SELECT * FROM generate_series(1, 10) i;
10657 -------------------------------------------------------------
10658 Insert on public.ftable
10659 Remote SQL: INSERT INTO public.batch_table(x) VALUES ($1)
10661 -> Function Scan on pg_catalog.generate_series i
10663 Function Call: generate_series(1, 10)
10666 INSERT INTO ftable SELECT * FROM generate_series(1, 10) i;
10667 INSERT INTO ftable SELECT * FROM generate_series(11, 31) i;
10668 INSERT INTO ftable VALUES (32);
10669 INSERT INTO ftable VALUES (33), (34);
10670 SELECT COUNT(*) FROM ftable;
10676 TRUNCATE batch_table;
10677 DROP FOREIGN TABLE ftable;
10678 -- Disable batch insert
10679 CREATE FOREIGN TABLE ftable ( x int ) SERVER loopback OPTIONS ( table_name 'batch_table', batch_size '1' );
10680 EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable VALUES (1), (2);
10682 -------------------------------------------------------------
10683 Insert on public.ftable
10684 Remote SQL: INSERT INTO public.batch_table(x) VALUES ($1)
10686 -> Values Scan on "*VALUES*"
10687 Output: "*VALUES*".column1
10690 INSERT INTO ftable VALUES (1), (2);
10691 SELECT COUNT(*) FROM ftable;
10697 -- Disable batch inserting into foreign tables with BEFORE ROW INSERT triggers
10698 -- even if the batch_size option is enabled.
10699 ALTER FOREIGN TABLE ftable OPTIONS ( SET batch_size '10' );
10700 CREATE TRIGGER trig_row_before BEFORE INSERT ON ftable
10701 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
10702 EXPLAIN (VERBOSE, COSTS OFF) INSERT INTO ftable VALUES (3), (4);
10704 -------------------------------------------------------------
10705 Insert on public.ftable
10706 Remote SQL: INSERT INTO public.batch_table(x) VALUES ($1)
10708 -> Values Scan on "*VALUES*"
10709 Output: "*VALUES*".column1
10712 INSERT INTO ftable VALUES (3), (4);
10713 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON ftable
10715 NOTICE: trig_row_before(23, skidoo) BEFORE ROW INSERT ON ftable
10717 SELECT COUNT(*) FROM ftable;
10724 DROP TRIGGER trig_row_before ON ftable;
10725 DROP FOREIGN TABLE ftable;
10726 DROP TABLE batch_table;
10727 -- Use partitioning
10728 CREATE TABLE batch_table ( x int ) PARTITION BY HASH (x);
10729 CREATE TABLE batch_table_p0 (LIKE batch_table);
10730 CREATE FOREIGN TABLE batch_table_p0f
10731 PARTITION OF batch_table
10732 FOR VALUES WITH (MODULUS 3, REMAINDER 0)
10734 OPTIONS (table_name 'batch_table_p0', batch_size '10');
10735 CREATE TABLE batch_table_p1 (LIKE batch_table);
10736 CREATE FOREIGN TABLE batch_table_p1f
10737 PARTITION OF batch_table
10738 FOR VALUES WITH (MODULUS 3, REMAINDER 1)
10740 OPTIONS (table_name 'batch_table_p1', batch_size '1');
10741 CREATE TABLE batch_table_p2
10742 PARTITION OF batch_table
10743 FOR VALUES WITH (MODULUS 3, REMAINDER 2);
10744 INSERT INTO batch_table SELECT * FROM generate_series(1, 66) i;
10745 SELECT COUNT(*) FROM batch_table;
10752 DROP TABLE batch_table;
10753 DROP TABLE batch_table_p0;
10754 DROP TABLE batch_table_p1;
10755 -- Check that batched mode also works for some inserts made during
10756 -- cross-partition updates
10757 CREATE TABLE batch_cp_upd_test (a int) PARTITION BY LIST (a);
10758 CREATE TABLE batch_cp_upd_test1 (LIKE batch_cp_upd_test);
10759 CREATE FOREIGN TABLE batch_cp_upd_test1_f
10760 PARTITION OF batch_cp_upd_test
10763 OPTIONS (table_name 'batch_cp_upd_test1', batch_size '10');
10764 CREATE TABLE batch_cp_upd_test2 PARTITION OF batch_cp_upd_test
10766 CREATE TABLE batch_cp_upd_test3 (LIKE batch_cp_upd_test);
10767 CREATE FOREIGN TABLE batch_cp_upd_test3_f
10768 PARTITION OF batch_cp_upd_test
10771 OPTIONS (table_name 'batch_cp_upd_test3', batch_size '1');
10772 -- Create statement triggers on remote tables that "log" any INSERTs
10773 -- performed on them.
10774 CREATE TABLE cmdlog (cmd text);
10775 CREATE FUNCTION log_stmt() RETURNS TRIGGER LANGUAGE plpgsql AS $$
10776 BEGIN INSERT INTO public.cmdlog VALUES (TG_OP || ' on ' || TG_RELNAME); RETURN NULL; END;
10778 CREATE TRIGGER stmt_trig AFTER INSERT ON batch_cp_upd_test1
10779 FOR EACH STATEMENT EXECUTE FUNCTION log_stmt();
10780 CREATE TRIGGER stmt_trig AFTER INSERT ON batch_cp_upd_test3
10781 FOR EACH STATEMENT EXECUTE FUNCTION log_stmt();
10782 -- This update moves rows from the local partition 'batch_cp_upd_test2' to the
10783 -- foreign partition 'batch_cp_upd_test1', one that has insert batching
10784 -- enabled, so a single INSERT for both rows.
10785 INSERT INTO batch_cp_upd_test VALUES (2), (2);
10786 UPDATE batch_cp_upd_test t SET a = 1 FROM (VALUES (1), (2)) s(a) WHERE t.a = s.a AND s.a = 2;
10787 -- This one moves rows from the local partition 'batch_cp_upd_test2' to the
10788 -- foreign partition 'batch_cp_upd_test2', one that has insert batching
10789 -- disabled, so separate INSERTs for the two rows.
10790 INSERT INTO batch_cp_upd_test VALUES (2), (2);
10791 UPDATE batch_cp_upd_test t SET a = 3 FROM (VALUES (1), (2)) s(a) WHERE t.a = s.a AND s.a = 2;
10792 SELECT tableoid::regclass, * FROM batch_cp_upd_test ORDER BY 1;
10794 ----------------------+---
10795 batch_cp_upd_test1_f | 1
10796 batch_cp_upd_test1_f | 1
10797 batch_cp_upd_test3_f | 3
10798 batch_cp_upd_test3_f | 3
10801 -- Should see 1 INSERT on batch_cp_upd_test1 and 2 on batch_cp_upd_test3 as
10802 -- described above.
10803 SELECT * FROM cmdlog ORDER BY 1;
10805 ------------------------------
10806 INSERT on batch_cp_upd_test1
10807 INSERT on batch_cp_upd_test3
10808 INSERT on batch_cp_upd_test3
10812 DROP TABLE batch_cp_upd_test;
10813 DROP TABLE batch_cp_upd_test1;
10814 DROP TABLE batch_cp_upd_test3;
10816 DROP FUNCTION log_stmt();
10817 -- Use partitioning
10818 ALTER SERVER loopback OPTIONS (ADD batch_size '10');
10819 CREATE TABLE batch_table ( x int, field1 text, field2 text) PARTITION BY HASH (x);
10820 CREATE TABLE batch_table_p0 (LIKE batch_table);
10821 ALTER TABLE batch_table_p0 ADD CONSTRAINT p0_pkey PRIMARY KEY (x);
10822 CREATE FOREIGN TABLE batch_table_p0f
10823 PARTITION OF batch_table
10824 FOR VALUES WITH (MODULUS 2, REMAINDER 0)
10826 OPTIONS (table_name 'batch_table_p0');
10827 CREATE TABLE batch_table_p1 (LIKE batch_table);
10828 ALTER TABLE batch_table_p1 ADD CONSTRAINT p1_pkey PRIMARY KEY (x);
10829 CREATE FOREIGN TABLE batch_table_p1f
10830 PARTITION OF batch_table
10831 FOR VALUES WITH (MODULUS 2, REMAINDER 1)
10833 OPTIONS (table_name 'batch_table_p1');
10834 INSERT INTO batch_table SELECT i, 'test'||i, 'test'|| i FROM generate_series(1, 50) i;
10835 SELECT COUNT(*) FROM batch_table;
10841 SELECT * FROM batch_table ORDER BY x;
10842 x | field1 | field2
10843 ----+--------+--------
10853 10 | test10 | test10
10854 11 | test11 | test11
10855 12 | test12 | test12
10856 13 | test13 | test13
10857 14 | test14 | test14
10858 15 | test15 | test15
10859 16 | test16 | test16
10860 17 | test17 | test17
10861 18 | test18 | test18
10862 19 | test19 | test19
10863 20 | test20 | test20
10864 21 | test21 | test21
10865 22 | test22 | test22
10866 23 | test23 | test23
10867 24 | test24 | test24
10868 25 | test25 | test25
10869 26 | test26 | test26
10870 27 | test27 | test27
10871 28 | test28 | test28
10872 29 | test29 | test29
10873 30 | test30 | test30
10874 31 | test31 | test31
10875 32 | test32 | test32
10876 33 | test33 | test33
10877 34 | test34 | test34
10878 35 | test35 | test35
10879 36 | test36 | test36
10880 37 | test37 | test37
10881 38 | test38 | test38
10882 39 | test39 | test39
10883 40 | test40 | test40
10884 41 | test41 | test41
10885 42 | test42 | test42
10886 43 | test43 | test43
10887 44 | test44 | test44
10888 45 | test45 | test45
10889 46 | test46 | test46
10890 47 | test47 | test47
10891 48 | test48 | test48
10892 49 | test49 | test49
10893 50 | test50 | test50
10897 DROP TABLE batch_table;
10898 DROP TABLE batch_table_p0;
10899 DROP TABLE batch_table_p1;
10900 ALTER SERVER loopback OPTIONS (DROP batch_size);
10901 -- Test that pending inserts are handled properly when needed
10902 CREATE TABLE batch_table (a text, b int);
10903 CREATE FOREIGN TABLE ftable (a text, b int)
10905 OPTIONS (table_name 'batch_table', batch_size '2');
10906 CREATE TABLE ltable (a text, b int);
10907 CREATE FUNCTION ftable_rowcount_trigf() RETURNS trigger LANGUAGE plpgsql AS
10910 raise notice '%: there are % rows in ftable',
10911 TG_NAME, (SELECT count(*) FROM ftable);
10912 if TG_OP = 'DELETE' then
10919 CREATE TRIGGER ftable_rowcount_trigger
10920 BEFORE INSERT OR UPDATE OR DELETE ON ltable
10921 FOR EACH ROW EXECUTE PROCEDURE ftable_rowcount_trigf();
10923 INSERT INTO ltable VALUES ('AAA', 42), ('BBB', 42) RETURNING *
10925 INSERT INTO ftable SELECT * FROM t;
10926 NOTICE: ftable_rowcount_trigger: there are 0 rows in ftable
10927 NOTICE: ftable_rowcount_trigger: there are 1 rows in ftable
10928 SELECT * FROM ltable;
10935 SELECT * FROM ftable;
10942 DELETE FROM ftable;
10944 UPDATE ltable SET b = b + 100 RETURNING *
10946 INSERT INTO ftable SELECT * FROM t;
10947 NOTICE: ftable_rowcount_trigger: there are 0 rows in ftable
10948 NOTICE: ftable_rowcount_trigger: there are 1 rows in ftable
10949 SELECT * FROM ltable;
10956 SELECT * FROM ftable;
10963 DELETE FROM ftable;
10965 DELETE FROM ltable RETURNING *
10967 INSERT INTO ftable SELECT * FROM t;
10968 NOTICE: ftable_rowcount_trigger: there are 0 rows in ftable
10969 NOTICE: ftable_rowcount_trigger: there are 1 rows in ftable
10970 SELECT * FROM ltable;
10975 SELECT * FROM ftable;
10982 DELETE FROM ftable;
10984 DROP FOREIGN TABLE ftable;
10985 DROP TABLE batch_table;
10986 DROP TRIGGER ftable_rowcount_trigger ON ltable;
10988 CREATE TABLE parent (a text, b int) PARTITION BY LIST (a);
10989 CREATE TABLE batch_table (a text, b int);
10990 CREATE FOREIGN TABLE ftable
10991 PARTITION OF parent
10992 FOR VALUES IN ('AAA')
10994 OPTIONS (table_name 'batch_table', batch_size '2');
10995 CREATE TABLE ltable
10996 PARTITION OF parent
10997 FOR VALUES IN ('BBB');
10998 CREATE TRIGGER ftable_rowcount_trigger
10999 BEFORE INSERT ON ltable
11000 FOR EACH ROW EXECUTE PROCEDURE ftable_rowcount_trigf();
11001 INSERT INTO parent VALUES ('AAA', 42), ('BBB', 42), ('AAA', 42), ('BBB', 42);
11002 NOTICE: ftable_rowcount_trigger: there are 1 rows in ftable
11003 NOTICE: ftable_rowcount_trigger: there are 2 rows in ftable
11004 SELECT tableoid::regclass, * FROM parent;
11006 ----------+-----+----
11014 DROP FOREIGN TABLE ftable;
11015 DROP TABLE batch_table;
11016 DROP TRIGGER ftable_rowcount_trigger ON ltable;
11019 DROP FUNCTION ftable_rowcount_trigf;
11020 -- ===================================================================
11021 -- test asynchronous execution
11022 -- ===================================================================
11023 ALTER SERVER loopback OPTIONS (DROP extensions);
11024 ALTER SERVER loopback OPTIONS (ADD async_capable 'true');
11025 ALTER SERVER loopback2 OPTIONS (ADD async_capable 'true');
11026 CREATE TABLE async_pt (a int, b int, c text) PARTITION BY RANGE (a);
11027 CREATE TABLE base_tbl1 (a int, b int, c text);
11028 CREATE TABLE base_tbl2 (a int, b int, c text);
11029 CREATE FOREIGN TABLE async_p1 PARTITION OF async_pt FOR VALUES FROM (1000) TO (2000)
11030 SERVER loopback OPTIONS (table_name 'base_tbl1');
11031 CREATE FOREIGN TABLE async_p2 PARTITION OF async_pt FOR VALUES FROM (2000) TO (3000)
11032 SERVER loopback2 OPTIONS (table_name 'base_tbl2');
11033 INSERT INTO async_p1 SELECT 1000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i;
11034 INSERT INTO async_p2 SELECT 2000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i;
11037 CREATE TABLE result_tbl (a int, b int, c text);
11038 EXPLAIN (VERBOSE, COSTS OFF)
11039 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b % 100 = 0;
11041 ----------------------------------------------------------------------------------------
11042 Insert on public.result_tbl
11044 -> Async Foreign Scan on public.async_p1 async_pt_1
11045 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11046 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE (((b % 100) = 0))
11047 -> Async Foreign Scan on public.async_p2 async_pt_2
11048 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11049 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE (((b % 100) = 0))
11052 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b % 100 = 0;
11053 SELECT * FROM result_tbl ORDER BY a;
11055 ------+-----+------
11078 DELETE FROM result_tbl;
11079 EXPLAIN (VERBOSE, COSTS OFF)
11080 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11082 ----------------------------------------------------------------
11083 Insert on public.result_tbl
11085 -> Async Foreign Scan on public.async_p1 async_pt_1
11086 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11087 Filter: (async_pt_1.b === 505)
11088 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11089 -> Async Foreign Scan on public.async_p2 async_pt_2
11090 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11091 Filter: (async_pt_2.b === 505)
11092 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11095 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11096 SELECT * FROM result_tbl ORDER BY a;
11098 ------+-----+------
11103 DELETE FROM result_tbl;
11104 EXPLAIN (VERBOSE, COSTS OFF)
11105 INSERT INTO result_tbl SELECT a, b, 'AAA' || c FROM async_pt WHERE b === 505;
11107 ---------------------------------------------------------------------------------
11108 Insert on public.result_tbl
11110 -> Async Foreign Scan on public.async_p1 async_pt_1
11111 Output: async_pt_1.a, async_pt_1.b, ('AAA'::text || async_pt_1.c)
11112 Filter: (async_pt_1.b === 505)
11113 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11114 -> Async Foreign Scan on public.async_p2 async_pt_2
11115 Output: async_pt_2.a, async_pt_2.b, ('AAA'::text || async_pt_2.c)
11116 Filter: (async_pt_2.b === 505)
11117 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11120 INSERT INTO result_tbl SELECT a, b, 'AAA' || c FROM async_pt WHERE b === 505;
11121 SELECT * FROM result_tbl ORDER BY a;
11123 ------+-----+---------
11124 1505 | 505 | AAA0505
11125 2505 | 505 | AAA0505
11128 DELETE FROM result_tbl;
11129 -- Test error handling, if accessing one of the foreign partitions errors out
11130 CREATE FOREIGN TABLE async_p_broken PARTITION OF async_pt FOR VALUES FROM (10000) TO (10001)
11131 SERVER loopback OPTIONS (table_name 'non_existent_table');
11132 SELECT * FROM async_pt;
11133 ERROR: relation "public.non_existent_table" does not exist
11134 CONTEXT: remote SQL command: SELECT a, b, c FROM public.non_existent_table
11135 DROP FOREIGN TABLE async_p_broken;
11136 -- Check case where multiple partitions use the same connection
11137 CREATE TABLE base_tbl3 (a int, b int, c text);
11138 CREATE FOREIGN TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000)
11139 SERVER loopback2 OPTIONS (table_name 'base_tbl3');
11140 INSERT INTO async_p3 SELECT 3000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i;
11142 EXPLAIN (VERBOSE, COSTS OFF)
11143 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11145 ----------------------------------------------------------------
11146 Insert on public.result_tbl
11148 -> Async Foreign Scan on public.async_p1 async_pt_1
11149 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11150 Filter: (async_pt_1.b === 505)
11151 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11152 -> Async Foreign Scan on public.async_p2 async_pt_2
11153 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11154 Filter: (async_pt_2.b === 505)
11155 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11156 -> Async Foreign Scan on public.async_p3 async_pt_3
11157 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11158 Filter: (async_pt_3.b === 505)
11159 Remote SQL: SELECT a, b, c FROM public.base_tbl3
11162 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11163 SELECT * FROM result_tbl ORDER BY a;
11165 ------+-----+------
11171 DELETE FROM result_tbl;
11172 DROP FOREIGN TABLE async_p3;
11173 DROP TABLE base_tbl3;
11174 -- Check case where the partitioned table has local/remote partitions
11175 CREATE TABLE async_p3 PARTITION OF async_pt FOR VALUES FROM (3000) TO (4000);
11176 INSERT INTO async_p3 SELECT 3000 + i, i, to_char(i, 'FM0000') FROM generate_series(0, 999, 5) i;
11178 EXPLAIN (VERBOSE, COSTS OFF)
11179 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11181 ----------------------------------------------------------------
11182 Insert on public.result_tbl
11184 -> Async Foreign Scan on public.async_p1 async_pt_1
11185 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11186 Filter: (async_pt_1.b === 505)
11187 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11188 -> Async Foreign Scan on public.async_p2 async_pt_2
11189 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11190 Filter: (async_pt_2.b === 505)
11191 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11192 -> Seq Scan on public.async_p3 async_pt_3
11193 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11194 Filter: (async_pt_3.b === 505)
11197 INSERT INTO result_tbl SELECT * FROM async_pt WHERE b === 505;
11198 SELECT * FROM result_tbl ORDER BY a;
11200 ------+-----+------
11206 DELETE FROM result_tbl;
11207 -- partitionwise joins
11208 SET enable_partitionwise_join TO true;
11209 CREATE TABLE join_tbl (a1 int, b1 int, c1 text, a2 int, b2 int, c2 text);
11210 EXPLAIN (VERBOSE, COSTS OFF)
11211 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;
11213 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
11214 Insert on public.join_tbl
11216 -> Async Foreign Scan
11217 Output: t1_1.a, t1_1.b, t1_1.c, t2_1.a, t2_1.b, t2_1.c
11218 Relations: (public.async_p1 t1_1) INNER JOIN (public.async_p1 t2_1)
11219 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))))
11220 -> Async Foreign Scan
11221 Output: t1_2.a, t1_2.b, t1_2.c, t2_2.a, t2_2.b, t2_2.c
11222 Relations: (public.async_p2 t1_2) INNER JOIN (public.async_p2 t2_2)
11223 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))))
11225 Output: t1_3.a, t1_3.b, t1_3.c, t2_3.a, t2_3.b, t2_3.c
11226 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.b = t1_3.b))
11227 -> Seq Scan on public.async_p3 t2_3
11228 Output: t2_3.a, t2_3.b, t2_3.c
11230 Output: t1_3.a, t1_3.b, t1_3.c
11231 -> Seq Scan on public.async_p3 t1_3
11232 Output: t1_3.a, t1_3.b, t1_3.c
11233 Filter: ((t1_3.b % 100) = 0)
11236 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 SELECT * FROM join_tbl ORDER BY a1;
11238 a1 | b1 | c1 | a2 | b2 | c2
11239 ------+-----+------+------+-----+------
11240 1000 | 0 | 0000 | 1000 | 0 | 0000
11241 1100 | 100 | 0100 | 1100 | 100 | 0100
11242 1200 | 200 | 0200 | 1200 | 200 | 0200
11243 1300 | 300 | 0300 | 1300 | 300 | 0300
11244 1400 | 400 | 0400 | 1400 | 400 | 0400
11245 1500 | 500 | 0500 | 1500 | 500 | 0500
11246 1600 | 600 | 0600 | 1600 | 600 | 0600
11247 1700 | 700 | 0700 | 1700 | 700 | 0700
11248 1800 | 800 | 0800 | 1800 | 800 | 0800
11249 1900 | 900 | 0900 | 1900 | 900 | 0900
11250 2000 | 0 | 0000 | 2000 | 0 | 0000
11251 2100 | 100 | 0100 | 2100 | 100 | 0100
11252 2200 | 200 | 0200 | 2200 | 200 | 0200
11253 2300 | 300 | 0300 | 2300 | 300 | 0300
11254 2400 | 400 | 0400 | 2400 | 400 | 0400
11255 2500 | 500 | 0500 | 2500 | 500 | 0500
11256 2600 | 600 | 0600 | 2600 | 600 | 0600
11257 2700 | 700 | 0700 | 2700 | 700 | 0700
11258 2800 | 800 | 0800 | 2800 | 800 | 0800
11259 2900 | 900 | 0900 | 2900 | 900 | 0900
11260 3000 | 0 | 0000 | 3000 | 0 | 0000
11261 3100 | 100 | 0100 | 3100 | 100 | 0100
11262 3200 | 200 | 0200 | 3200 | 200 | 0200
11263 3300 | 300 | 0300 | 3300 | 300 | 0300
11264 3400 | 400 | 0400 | 3400 | 400 | 0400
11265 3500 | 500 | 0500 | 3500 | 500 | 0500
11266 3600 | 600 | 0600 | 3600 | 600 | 0600
11267 3700 | 700 | 0700 | 3700 | 700 | 0700
11268 3800 | 800 | 0800 | 3800 | 800 | 0800
11269 3900 | 900 | 0900 | 3900 | 900 | 0900
11272 DELETE FROM join_tbl;
11273 EXPLAIN (VERBOSE, COSTS OFF)
11274 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;
11276 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
11277 Insert on public.join_tbl
11279 -> Async Foreign Scan
11280 Output: t1_1.a, t1_1.b, ('AAA'::text || t1_1.c), t2_1.a, t2_1.b, ('AAA'::text || t2_1.c)
11281 Relations: (public.async_p1 t1_1) INNER JOIN (public.async_p1 t2_1)
11282 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))))
11283 -> Async Foreign Scan
11284 Output: t1_2.a, t1_2.b, ('AAA'::text || t1_2.c), t2_2.a, t2_2.b, ('AAA'::text || t2_2.c)
11285 Relations: (public.async_p2 t1_2) INNER JOIN (public.async_p2 t2_2)
11286 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))))
11288 Output: t1_3.a, t1_3.b, ('AAA'::text || t1_3.c), t2_3.a, t2_3.b, ('AAA'::text || t2_3.c)
11289 Hash Cond: ((t2_3.a = t1_3.a) AND (t2_3.b = t1_3.b))
11290 -> Seq Scan on public.async_p3 t2_3
11291 Output: t2_3.a, t2_3.b, t2_3.c
11293 Output: t1_3.a, t1_3.b, t1_3.c
11294 -> Seq Scan on public.async_p3 t1_3
11295 Output: t1_3.a, t1_3.b, t1_3.c
11296 Filter: ((t1_3.b % 100) = 0)
11299 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 SELECT * FROM join_tbl ORDER BY a1;
11301 a1 | b1 | c1 | a2 | b2 | c2
11302 ------+-----+---------+------+-----+---------
11303 1000 | 0 | AAA0000 | 1000 | 0 | AAA0000
11304 1100 | 100 | AAA0100 | 1100 | 100 | AAA0100
11305 1200 | 200 | AAA0200 | 1200 | 200 | AAA0200
11306 1300 | 300 | AAA0300 | 1300 | 300 | AAA0300
11307 1400 | 400 | AAA0400 | 1400 | 400 | AAA0400
11308 1500 | 500 | AAA0500 | 1500 | 500 | AAA0500
11309 1600 | 600 | AAA0600 | 1600 | 600 | AAA0600
11310 1700 | 700 | AAA0700 | 1700 | 700 | AAA0700
11311 1800 | 800 | AAA0800 | 1800 | 800 | AAA0800
11312 1900 | 900 | AAA0900 | 1900 | 900 | AAA0900
11313 2000 | 0 | AAA0000 | 2000 | 0 | AAA0000
11314 2100 | 100 | AAA0100 | 2100 | 100 | AAA0100
11315 2200 | 200 | AAA0200 | 2200 | 200 | AAA0200
11316 2300 | 300 | AAA0300 | 2300 | 300 | AAA0300
11317 2400 | 400 | AAA0400 | 2400 | 400 | AAA0400
11318 2500 | 500 | AAA0500 | 2500 | 500 | AAA0500
11319 2600 | 600 | AAA0600 | 2600 | 600 | AAA0600
11320 2700 | 700 | AAA0700 | 2700 | 700 | AAA0700
11321 2800 | 800 | AAA0800 | 2800 | 800 | AAA0800
11322 2900 | 900 | AAA0900 | 2900 | 900 | AAA0900
11323 3000 | 0 | AAA0000 | 3000 | 0 | AAA0000
11324 3100 | 100 | AAA0100 | 3100 | 100 | AAA0100
11325 3200 | 200 | AAA0200 | 3200 | 200 | AAA0200
11326 3300 | 300 | AAA0300 | 3300 | 300 | AAA0300
11327 3400 | 400 | AAA0400 | 3400 | 400 | AAA0400
11328 3500 | 500 | AAA0500 | 3500 | 500 | AAA0500
11329 3600 | 600 | AAA0600 | 3600 | 600 | AAA0600
11330 3700 | 700 | AAA0700 | 3700 | 700 | AAA0700
11331 3800 | 800 | AAA0800 | 3800 | 800 | AAA0800
11332 3900 | 900 | AAA0900 | 3900 | 900 | AAA0900
11335 DELETE FROM join_tbl;
11336 RESET enable_partitionwise_join;
11337 -- Test rescan of an async Append node with do_exec_prune=false
11338 SET enable_hashjoin TO false;
11339 EXPLAIN (VERBOSE, COSTS OFF)
11340 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;
11342 ----------------------------------------------------------------------------------------
11343 Insert on public.join_tbl
11345 Output: t1.a, t1.b, t1.c, t2.a, t2.b, t2.c
11346 Join Filter: ((t1.a = t2.a) AND (t1.b = t2.b))
11347 -> Foreign Scan on public.async_p1 t1
11348 Output: t1.a, t1.b, t1.c
11349 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE (((b % 100) = 0))
11351 -> Async Foreign Scan on public.async_p1 t2_1
11352 Output: t2_1.a, t2_1.b, t2_1.c
11353 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11354 -> Async Foreign Scan on public.async_p2 t2_2
11355 Output: t2_2.a, t2_2.b, t2_2.c
11356 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11357 -> Seq Scan on public.async_p3 t2_3
11358 Output: t2_3.a, t2_3.b, t2_3.c
11361 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;
11362 SELECT * FROM join_tbl ORDER BY a1;
11363 a1 | b1 | c1 | a2 | b2 | c2
11364 ------+-----+------+------+-----+------
11365 1000 | 0 | 0000 | 1000 | 0 | 0000
11366 1100 | 100 | 0100 | 1100 | 100 | 0100
11367 1200 | 200 | 0200 | 1200 | 200 | 0200
11368 1300 | 300 | 0300 | 1300 | 300 | 0300
11369 1400 | 400 | 0400 | 1400 | 400 | 0400
11370 1500 | 500 | 0500 | 1500 | 500 | 0500
11371 1600 | 600 | 0600 | 1600 | 600 | 0600
11372 1700 | 700 | 0700 | 1700 | 700 | 0700
11373 1800 | 800 | 0800 | 1800 | 800 | 0800
11374 1900 | 900 | 0900 | 1900 | 900 | 0900
11377 DELETE FROM join_tbl;
11378 RESET enable_hashjoin;
11379 -- Test interaction of async execution with plan-time partition pruning
11380 EXPLAIN (VERBOSE, COSTS OFF)
11381 SELECT * FROM async_pt WHERE a < 3000;
11383 -----------------------------------------------------------------------------
11385 -> Async Foreign Scan on public.async_p1 async_pt_1
11386 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11387 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < 3000))
11388 -> Async Foreign Scan on public.async_p2 async_pt_2
11389 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11390 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a < 3000))
11393 EXPLAIN (VERBOSE, COSTS OFF)
11394 SELECT * FROM async_pt WHERE a < 2000;
11396 -----------------------------------------------------------------------
11397 Foreign Scan on public.async_p1 async_pt
11398 Output: async_pt.a, async_pt.b, async_pt.c
11399 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < 2000))
11402 -- Test interaction of async execution with run-time partition pruning
11403 SET plan_cache_mode TO force_generic_plan;
11404 PREPARE async_pt_query (int, int) AS
11405 INSERT INTO result_tbl SELECT * FROM async_pt WHERE a < $1 AND b === $2;
11406 EXPLAIN (VERBOSE, COSTS OFF)
11407 EXECUTE async_pt_query (3000, 505);
11409 ------------------------------------------------------------------------------------------
11410 Insert on public.result_tbl
11412 Subplans Removed: 1
11413 -> Async Foreign Scan on public.async_p1 async_pt_1
11414 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11415 Filter: (async_pt_1.b === $2)
11416 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < $1::integer))
11417 -> Async Foreign Scan on public.async_p2 async_pt_2
11418 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11419 Filter: (async_pt_2.b === $2)
11420 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a < $1::integer))
11423 EXECUTE async_pt_query (3000, 505);
11424 SELECT * FROM result_tbl ORDER BY a;
11426 ------+-----+------
11431 DELETE FROM result_tbl;
11432 EXPLAIN (VERBOSE, COSTS OFF)
11433 EXECUTE async_pt_query (2000, 505);
11435 ------------------------------------------------------------------------------------------
11436 Insert on public.result_tbl
11438 Subplans Removed: 2
11439 -> Async Foreign Scan on public.async_p1 async_pt_1
11440 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11441 Filter: (async_pt_1.b === $2)
11442 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < $1::integer))
11445 EXECUTE async_pt_query (2000, 505);
11446 SELECT * FROM result_tbl ORDER BY a;
11448 ------+-----+------
11452 DELETE FROM result_tbl;
11453 RESET plan_cache_mode;
11454 CREATE TABLE local_tbl(a int, b int, c text);
11455 INSERT INTO local_tbl VALUES (1505, 505, 'foo'), (2505, 505, 'bar');
11457 CREATE INDEX base_tbl1_idx ON base_tbl1 (a);
11458 CREATE INDEX base_tbl2_idx ON base_tbl2 (a);
11459 CREATE INDEX async_p3_idx ON async_p3 (a);
11463 ALTER FOREIGN TABLE async_p1 OPTIONS (use_remote_estimate 'true');
11464 ALTER FOREIGN TABLE async_p2 OPTIONS (use_remote_estimate 'true');
11465 EXPLAIN (VERBOSE, COSTS OFF)
11466 SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar';
11468 ------------------------------------------------------------------------------------------
11470 Output: local_tbl.a, local_tbl.b, local_tbl.c, async_pt.a, async_pt.b, async_pt.c
11471 -> Seq Scan on public.local_tbl
11472 Output: local_tbl.a, local_tbl.b, local_tbl.c
11473 Filter: (local_tbl.c = 'bar'::text)
11475 -> Async Foreign Scan on public.async_p1 async_pt_1
11476 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11477 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a = $1::integer))
11478 -> Async Foreign Scan on public.async_p2 async_pt_2
11479 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11480 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a = $1::integer))
11481 -> Seq Scan on public.async_p3 async_pt_3
11482 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11483 Filter: (async_pt_3.a = local_tbl.a)
11486 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
11487 SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar';
11489 -------------------------------------------------------------------------------
11490 Nested Loop (actual rows=1 loops=1)
11491 -> Seq Scan on local_tbl (actual rows=1 loops=1)
11492 Filter: (c = 'bar'::text)
11493 Rows Removed by Filter: 1
11494 -> Append (actual rows=1 loops=1)
11495 -> Async Foreign Scan on async_p1 async_pt_1 (never executed)
11496 -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=1 loops=1)
11497 -> Seq Scan on async_p3 async_pt_3 (never executed)
11498 Filter: (a = local_tbl.a)
11501 SELECT * FROM local_tbl, async_pt WHERE local_tbl.a = async_pt.a AND local_tbl.c = 'bar';
11502 a | b | c | a | b | c
11503 ------+-----+-----+------+-----+------
11504 2505 | 505 | bar | 2505 | 505 | 0505
11507 ALTER FOREIGN TABLE async_p1 OPTIONS (DROP use_remote_estimate);
11508 ALTER FOREIGN TABLE async_p2 OPTIONS (DROP use_remote_estimate);
11509 DROP TABLE local_tbl;
11510 DROP INDEX base_tbl1_idx;
11511 DROP INDEX base_tbl2_idx;
11512 DROP INDEX async_p3_idx;
11514 EXPLAIN (VERBOSE, COSTS OFF)
11515 INSERT INTO result_tbl
11516 (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10)
11518 (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10);
11520 -----------------------------------------------------------------------------------------------------------------
11521 Insert on public.result_tbl
11523 Output: async_p1.a, async_p1.b, (('AAA'::text || async_p1.c))
11524 Group Key: async_p1.a, async_p1.b, (('AAA'::text || async_p1.c))
11526 -> Async Foreign Scan on public.async_p1
11527 Output: async_p1.a, async_p1.b, ('AAA'::text || async_p1.c)
11528 Remote SQL: SELECT a, b, c FROM public.base_tbl1 ORDER BY a ASC NULLS LAST LIMIT 10::bigint
11529 -> Async Foreign Scan on public.async_p2
11530 Output: async_p2.a, async_p2.b, ('AAA'::text || async_p2.c)
11531 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((b < 10))
11534 INSERT INTO result_tbl
11535 (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10)
11537 (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10);
11538 SELECT * FROM result_tbl ORDER BY a;
11540 ------+----+---------
11543 1010 | 10 | AAA0010
11544 1015 | 15 | AAA0015
11545 1020 | 20 | AAA0020
11546 1025 | 25 | AAA0025
11547 1030 | 30 | AAA0030
11548 1035 | 35 | AAA0035
11549 1040 | 40 | AAA0040
11550 1045 | 45 | AAA0045
11555 DELETE FROM result_tbl;
11556 EXPLAIN (VERBOSE, COSTS OFF)
11557 INSERT INTO result_tbl
11558 (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10)
11560 (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10);
11562 -----------------------------------------------------------------------------------------------------------
11563 Insert on public.result_tbl
11565 -> Async Foreign Scan on public.async_p1
11566 Output: async_p1.a, async_p1.b, ('AAA'::text || async_p1.c)
11567 Remote SQL: SELECT a, b, c FROM public.base_tbl1 ORDER BY a ASC NULLS LAST LIMIT 10::bigint
11568 -> Async Foreign Scan on public.async_p2
11569 Output: async_p2.a, async_p2.b, ('AAA'::text || async_p2.c)
11570 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((b < 10))
11573 INSERT INTO result_tbl
11574 (SELECT a, b, 'AAA' || c FROM async_p1 ORDER BY a LIMIT 10)
11576 (SELECT a, b, 'AAA' || c FROM async_p2 WHERE b < 10);
11577 SELECT * FROM result_tbl ORDER BY a;
11579 ------+----+---------
11582 1010 | 10 | AAA0010
11583 1015 | 15 | AAA0015
11584 1020 | 20 | AAA0020
11585 1025 | 25 | AAA0025
11586 1030 | 30 | AAA0030
11587 1035 | 35 | AAA0035
11588 1040 | 40 | AAA0040
11589 1045 | 45 | AAA0045
11594 DELETE FROM result_tbl;
11595 -- Disable async execution if we use gating Result nodes for pseudoconstant
11597 EXPLAIN (VERBOSE, COSTS OFF)
11598 SELECT * FROM async_pt WHERE CURRENT_USER = SESSION_USER;
11600 ----------------------------------------------------------------
11603 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11604 One-Time Filter: (CURRENT_USER = SESSION_USER)
11605 -> Foreign Scan on public.async_p1 async_pt_1
11606 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11607 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11609 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11610 One-Time Filter: (CURRENT_USER = SESSION_USER)
11611 -> Foreign Scan on public.async_p2 async_pt_2
11612 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11613 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11615 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11616 One-Time Filter: (CURRENT_USER = SESSION_USER)
11617 -> Seq Scan on public.async_p3 async_pt_3
11618 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11621 EXPLAIN (VERBOSE, COSTS OFF)
11622 (SELECT * FROM async_p1 WHERE CURRENT_USER = SESSION_USER)
11624 (SELECT * FROM async_p2 WHERE CURRENT_USER = SESSION_USER);
11626 ----------------------------------------------------------------
11629 Output: async_p1.a, async_p1.b, async_p1.c
11630 One-Time Filter: (CURRENT_USER = SESSION_USER)
11631 -> Foreign Scan on public.async_p1
11632 Output: async_p1.a, async_p1.b, async_p1.c
11633 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11635 Output: async_p2.a, async_p2.b, async_p2.c
11636 One-Time Filter: (CURRENT_USER = SESSION_USER)
11637 -> Foreign Scan on public.async_p2
11638 Output: async_p2.a, async_p2.b, async_p2.c
11639 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11642 EXPLAIN (VERBOSE, COSTS OFF)
11643 SELECT * FROM ((SELECT * FROM async_p1 WHERE b < 10) UNION ALL (SELECT * FROM async_p2 WHERE b < 10)) s WHERE CURRENT_USER = SESSION_USER;
11645 ---------------------------------------------------------------------------------
11648 Output: async_p1.a, async_p1.b, async_p1.c
11649 One-Time Filter: (CURRENT_USER = SESSION_USER)
11650 -> Foreign Scan on public.async_p1
11651 Output: async_p1.a, async_p1.b, async_p1.c
11652 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((b < 10))
11654 Output: async_p2.a, async_p2.b, async_p2.c
11655 One-Time Filter: (CURRENT_USER = SESSION_USER)
11656 -> Foreign Scan on public.async_p2
11657 Output: async_p2.a, async_p2.b, async_p2.c
11658 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((b < 10))
11661 -- Test that pending requests are processed properly
11662 SET enable_mergejoin TO false;
11663 SET enable_hashjoin TO false;
11664 EXPLAIN (VERBOSE, COSTS OFF)
11665 SELECT * FROM async_pt t1, async_p2 t2 WHERE t1.a = t2.a AND t1.b === 505;
11667 ----------------------------------------------------------------
11669 Output: t1.a, t1.b, t1.c, t2.a, t2.b, t2.c
11670 Join Filter: (t1.a = t2.a)
11672 -> Async Foreign Scan on public.async_p1 t1_1
11673 Output: t1_1.a, t1_1.b, t1_1.c
11674 Filter: (t1_1.b === 505)
11675 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11676 -> Async Foreign Scan on public.async_p2 t1_2
11677 Output: t1_2.a, t1_2.b, t1_2.c
11678 Filter: (t1_2.b === 505)
11679 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11680 -> Seq Scan on public.async_p3 t1_3
11681 Output: t1_3.a, t1_3.b, t1_3.c
11682 Filter: (t1_3.b === 505)
11684 Output: t2.a, t2.b, t2.c
11685 -> Foreign Scan on public.async_p2 t2
11686 Output: t2.a, t2.b, t2.c
11687 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11690 SELECT * FROM async_pt t1, async_p2 t2 WHERE t1.a = t2.a AND t1.b === 505;
11691 a | b | c | a | b | c
11692 ------+-----+------+------+-----+------
11693 2505 | 505 | 0505 | 2505 | 505 | 0505
11696 CREATE TABLE local_tbl (a int, b int, c text);
11697 INSERT INTO local_tbl VALUES (1505, 505, 'foo');
11699 EXPLAIN (VERBOSE, COSTS OFF)
11700 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;
11702 ----------------------------------------------------------------------------------------
11703 Nested Loop Left Join
11704 Output: t1.a, t1.b, t1.c, async_pt.a, async_pt.b, async_pt.c, ((InitPlan 1).col1)
11705 Join Filter: (t1.a = async_pt.a)
11710 -> Async Foreign Scan on public.async_p1 async_pt_4
11711 Remote SQL: SELECT NULL FROM public.base_tbl1 WHERE ((a < 3000))
11712 -> Async Foreign Scan on public.async_p2 async_pt_5
11713 Remote SQL: SELECT NULL FROM public.base_tbl2 WHERE ((a < 3000))
11714 -> Seq Scan on public.local_tbl t1
11715 Output: t1.a, t1.b, t1.c
11717 -> Async Foreign Scan on public.async_p1 async_pt_1
11718 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c, (InitPlan 1).col1
11719 Remote SQL: SELECT a, b, c FROM public.base_tbl1 WHERE ((a < 3000))
11720 -> Async Foreign Scan on public.async_p2 async_pt_2
11721 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c, (InitPlan 1).col1
11722 Remote SQL: SELECT a, b, c FROM public.base_tbl2 WHERE ((a < 3000))
11725 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
11726 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;
11728 -----------------------------------------------------------------------------------------
11729 Nested Loop Left Join (actual rows=1 loops=1)
11730 Join Filter: (t1.a = async_pt.a)
11731 Rows Removed by Join Filter: 399
11733 -> Aggregate (actual rows=1 loops=1)
11734 -> Append (actual rows=400 loops=1)
11735 -> Async Foreign Scan on async_p1 async_pt_4 (actual rows=200 loops=1)
11736 -> Async Foreign Scan on async_p2 async_pt_5 (actual rows=200 loops=1)
11737 -> Seq Scan on local_tbl t1 (actual rows=1 loops=1)
11738 -> Append (actual rows=400 loops=1)
11739 -> Async Foreign Scan on async_p1 async_pt_1 (actual rows=200 loops=1)
11740 -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=200 loops=1)
11743 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;
11744 a | b | c | a | b | c | count
11745 ------+-----+-----+------+-----+------+-------
11746 1505 | 505 | foo | 1505 | 505 | 0505 | 400
11749 EXPLAIN (VERBOSE, COSTS OFF)
11750 SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1;
11752 ----------------------------------------------------------------
11754 Output: t1.a, t1.b, t1.c
11756 -> Async Foreign Scan on public.async_p1 t1_1
11757 Output: t1_1.a, t1_1.b, t1_1.c
11758 Filter: (t1_1.b === 505)
11759 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11760 -> Async Foreign Scan on public.async_p2 t1_2
11761 Output: t1_2.a, t1_2.b, t1_2.c
11762 Filter: (t1_2.b === 505)
11763 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11764 -> Seq Scan on public.async_p3 t1_3
11765 Output: t1_3.a, t1_3.b, t1_3.c
11766 Filter: (t1_3.b === 505)
11769 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
11770 SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1;
11772 -------------------------------------------------------------------------
11773 Limit (actual rows=1 loops=1)
11774 -> Append (actual rows=1 loops=1)
11775 -> Async Foreign Scan on async_p1 t1_1 (actual rows=0 loops=1)
11776 Filter: (b === 505)
11777 -> Async Foreign Scan on async_p2 t1_2 (actual rows=0 loops=1)
11778 Filter: (b === 505)
11779 -> Seq Scan on async_p3 t1_3 (actual rows=1 loops=1)
11780 Filter: (b === 505)
11781 Rows Removed by Filter: 101
11784 SELECT * FROM async_pt t1 WHERE t1.b === 505 LIMIT 1;
11786 ------+-----+------
11790 -- Check with foreign modify
11791 CREATE TABLE base_tbl3 (a int, b int, c text);
11792 CREATE FOREIGN TABLE remote_tbl (a int, b int, c text)
11793 SERVER loopback OPTIONS (table_name 'base_tbl3');
11794 INSERT INTO remote_tbl VALUES (2505, 505, 'bar');
11795 CREATE TABLE base_tbl4 (a int, b int, c text);
11796 CREATE FOREIGN TABLE insert_tbl (a int, b int, c text)
11797 SERVER loopback OPTIONS (table_name 'base_tbl4');
11798 EXPLAIN (VERBOSE, COSTS OFF)
11799 INSERT INTO insert_tbl (SELECT * FROM local_tbl UNION ALL SELECT * FROM remote_tbl);
11801 -------------------------------------------------------------------------
11802 Insert on public.insert_tbl
11803 Remote SQL: INSERT INTO public.base_tbl4(a, b, c) VALUES ($1, $2, $3)
11806 -> Seq Scan on public.local_tbl
11807 Output: local_tbl.a, local_tbl.b, local_tbl.c
11808 -> Async Foreign Scan on public.remote_tbl
11809 Output: remote_tbl.a, remote_tbl.b, remote_tbl.c
11810 Remote SQL: SELECT a, b, c FROM public.base_tbl3
11813 INSERT INTO insert_tbl (SELECT * FROM local_tbl UNION ALL SELECT * FROM remote_tbl);
11814 SELECT * FROM insert_tbl ORDER BY a;
11821 -- Check with direct modify
11822 EXPLAIN (VERBOSE, COSTS OFF)
11823 WITH t AS (UPDATE remote_tbl SET c = c || c RETURNING *)
11824 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;
11826 ----------------------------------------------------------------------------------------
11827 Insert on public.join_tbl
11829 -> Update on public.remote_tbl
11830 Output: remote_tbl.a, remote_tbl.b, remote_tbl.c
11831 -> Foreign Update on public.remote_tbl
11832 Remote SQL: UPDATE public.base_tbl3 SET c = (c || c) RETURNING a, b, c
11833 -> Nested Loop Left Join
11834 Output: async_pt.a, async_pt.b, async_pt.c, t.a, t.b, t.c
11835 Join Filter: ((async_pt.a = t.a) AND (async_pt.b = t.b))
11837 -> Async Foreign Scan on public.async_p1 async_pt_1
11838 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11839 Filter: (async_pt_1.b === 505)
11840 Remote SQL: SELECT a, b, c FROM public.base_tbl1
11841 -> Async Foreign Scan on public.async_p2 async_pt_2
11842 Output: async_pt_2.a, async_pt_2.b, async_pt_2.c
11843 Filter: (async_pt_2.b === 505)
11844 Remote SQL: SELECT a, b, c FROM public.base_tbl2
11845 -> Seq Scan on public.async_p3 async_pt_3
11846 Output: async_pt_3.a, async_pt_3.b, async_pt_3.c
11847 Filter: (async_pt_3.b === 505)
11849 Output: t.a, t.b, t.c
11852 WITH t AS (UPDATE remote_tbl SET c = c || c RETURNING *)
11853 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;
11854 SELECT * FROM join_tbl ORDER BY a1;
11855 a1 | b1 | c1 | a2 | b2 | c2
11856 ------+-----+------+------+-----+--------
11857 1505 | 505 | 0505 | | |
11858 2505 | 505 | 0505 | 2505 | 505 | barbar
11859 3505 | 505 | 0505 | | |
11862 DELETE FROM join_tbl;
11863 DROP TABLE local_tbl;
11864 DROP FOREIGN TABLE remote_tbl;
11865 DROP FOREIGN TABLE insert_tbl;
11866 DROP TABLE base_tbl3;
11867 DROP TABLE base_tbl4;
11868 RESET enable_mergejoin;
11869 RESET enable_hashjoin;
11870 -- Test that UPDATE/DELETE with inherited target works with async_capable enabled
11871 EXPLAIN (VERBOSE, COSTS OFF)
11872 UPDATE async_pt SET c = c || c WHERE b = 0 RETURNING *;
11874 ----------------------------------------------------------------------------------------------------------
11875 Update on public.async_pt
11876 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11877 Foreign Update on public.async_p1 async_pt_1
11878 Foreign Update on public.async_p2 async_pt_2
11879 Update on public.async_p3 async_pt_3
11881 -> Foreign Update on public.async_p1 async_pt_1
11882 Remote SQL: UPDATE public.base_tbl1 SET c = (c || c) WHERE ((b = 0)) RETURNING a, b, c
11883 -> Foreign Update on public.async_p2 async_pt_2
11884 Remote SQL: UPDATE public.base_tbl2 SET c = (c || c) WHERE ((b = 0)) RETURNING a, b, c
11885 -> Seq Scan on public.async_p3 async_pt_3
11886 Output: (async_pt_3.c || async_pt_3.c), async_pt_3.tableoid, async_pt_3.ctid, NULL::record
11887 Filter: (async_pt_3.b = 0)
11890 UPDATE async_pt SET c = c || c WHERE b = 0 RETURNING *;
11892 ------+---+----------
11893 1000 | 0 | 00000000
11894 2000 | 0 | 00000000
11895 3000 | 0 | 00000000
11898 EXPLAIN (VERBOSE, COSTS OFF)
11899 DELETE FROM async_pt WHERE b = 0 RETURNING *;
11901 ------------------------------------------------------------------------------------------
11902 Delete on public.async_pt
11903 Output: async_pt_1.a, async_pt_1.b, async_pt_1.c
11904 Foreign Delete on public.async_p1 async_pt_1
11905 Foreign Delete on public.async_p2 async_pt_2
11906 Delete on public.async_p3 async_pt_3
11908 -> Foreign Delete on public.async_p1 async_pt_1
11909 Remote SQL: DELETE FROM public.base_tbl1 WHERE ((b = 0)) RETURNING a, b, c
11910 -> Foreign Delete on public.async_p2 async_pt_2
11911 Remote SQL: DELETE FROM public.base_tbl2 WHERE ((b = 0)) RETURNING a, b, c
11912 -> Seq Scan on public.async_p3 async_pt_3
11913 Output: async_pt_3.tableoid, async_pt_3.ctid
11914 Filter: (async_pt_3.b = 0)
11917 DELETE FROM async_pt WHERE b = 0 RETURNING *;
11919 ------+---+----------
11920 1000 | 0 | 00000000
11921 2000 | 0 | 00000000
11922 3000 | 0 | 00000000
11925 -- Check EXPLAIN ANALYZE for a query that scans empty partitions asynchronously
11926 DELETE FROM async_p1;
11927 DELETE FROM async_p2;
11928 DELETE FROM async_p3;
11929 EXPLAIN (ANALYZE, COSTS OFF, SUMMARY OFF, TIMING OFF)
11930 SELECT * FROM async_pt;
11932 -------------------------------------------------------------------------
11933 Append (actual rows=0 loops=1)
11934 -> Async Foreign Scan on async_p1 async_pt_1 (actual rows=0 loops=1)
11935 -> Async Foreign Scan on async_p2 async_pt_2 (actual rows=0 loops=1)
11936 -> Seq Scan on async_p3 async_pt_3 (actual rows=0 loops=1)
11940 DROP TABLE async_pt;
11941 DROP TABLE base_tbl1;
11942 DROP TABLE base_tbl2;
11943 DROP TABLE result_tbl;
11944 DROP TABLE join_tbl;
11945 -- Test that an asynchronous fetch is processed before restarting the scan in
11946 -- ReScanForeignScan
11947 CREATE TABLE base_tbl (a int, b int);
11948 INSERT INTO base_tbl VALUES (1, 11), (2, 22), (3, 33);
11949 CREATE FOREIGN TABLE foreign_tbl (b int)
11950 SERVER loopback OPTIONS (table_name 'base_tbl');
11951 CREATE FOREIGN TABLE foreign_tbl2 () INHERITS (foreign_tbl)
11952 SERVER loopback OPTIONS (table_name 'base_tbl');
11953 EXPLAIN (VERBOSE, COSTS OFF)
11954 SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl);
11956 ---------------------------------------------------------------------------------------------------------------
11957 Seq Scan on public.base_tbl
11959 Filter: (ANY ((base_tbl.a = (SubPlan 1).col1) AND ((random() > '0'::double precision) = (SubPlan 1).col2)))
11962 Output: base_tbl.a, (random() > '0'::double precision)
11964 -> Async Foreign Scan on public.foreign_tbl foreign_tbl_1
11965 Remote SQL: SELECT NULL FROM public.base_tbl
11966 -> Async Foreign Scan on public.foreign_tbl2 foreign_tbl_2
11967 Remote SQL: SELECT NULL FROM public.base_tbl
11970 SELECT a FROM base_tbl WHERE (a, random() > 0) IN (SELECT a, random() > 0 FROM foreign_tbl);
11979 DROP FOREIGN TABLE foreign_tbl CASCADE;
11980 NOTICE: drop cascades to foreign table foreign_tbl2
11981 DROP TABLE base_tbl;
11982 ALTER SERVER loopback OPTIONS (DROP async_capable);
11983 ALTER SERVER loopback2 OPTIONS (DROP async_capable);
11984 -- ===================================================================
11985 -- test invalid server, foreign table and foreign data wrapper options
11986 -- ===================================================================
11987 -- Invalid fdw_startup_cost option
11988 CREATE SERVER inv_scst FOREIGN DATA WRAPPER postgres_fdw
11989 OPTIONS(fdw_startup_cost '100$%$#$#');
11990 ERROR: invalid value for floating point option "fdw_startup_cost": 100$%$#$#
11991 -- Invalid fdw_tuple_cost option
11992 CREATE SERVER inv_scst FOREIGN DATA WRAPPER postgres_fdw
11993 OPTIONS(fdw_tuple_cost '100$%$#$#');
11994 ERROR: invalid value for floating point option "fdw_tuple_cost": 100$%$#$#
11995 -- Invalid fetch_size option
11996 CREATE FOREIGN TABLE inv_fsz (c1 int )
11997 SERVER loopback OPTIONS (fetch_size '100$%$#$#');
11998 ERROR: invalid value for integer option "fetch_size": 100$%$#$#
11999 -- Invalid batch_size option
12000 CREATE FOREIGN TABLE inv_bsz (c1 int )
12001 SERVER loopback OPTIONS (batch_size '100$%$#$#');
12002 ERROR: invalid value for integer option "batch_size": 100$%$#$#
12003 -- No option is allowed to be specified at foreign data wrapper level
12004 ALTER FOREIGN DATA WRAPPER postgres_fdw OPTIONS (nonexistent 'fdw');
12005 ERROR: invalid option "nonexistent"
12006 HINT: There are no valid options in this context.
12007 -- ===================================================================
12008 -- test postgres_fdw.application_name GUC
12009 -- ===================================================================
12010 -- To avoid race conditions in checking the remote session's application_name,
12011 -- use this view to make the remote session itself read its application_name.
12012 CREATE VIEW my_application_name AS
12013 SELECT application_name FROM pg_stat_activity WHERE pid = pg_backend_pid();
12014 CREATE FOREIGN TABLE remote_application_name (application_name text)
12016 OPTIONS (schema_name 'public', table_name 'my_application_name');
12017 SELECT count(*) FROM remote_application_name;
12023 -- Specify escape sequences in application_name option of a server
12024 -- object so as to test that they are replaced with status information
12025 -- expectedly. Note that we are also relying on ALTER SERVER to force
12026 -- the remote session to be restarted with its new application name.
12028 -- Since pg_stat_activity.application_name may be truncated to less than
12029 -- NAMEDATALEN characters, note that substring() needs to be used
12030 -- at the condition of test query to make sure that the string consisting
12031 -- of database name and process ID is also less than that.
12032 ALTER SERVER loopback2 OPTIONS (application_name 'fdw_%d%p');
12033 SELECT count(*) FROM remote_application_name
12034 WHERE application_name =
12035 substring('fdw_' || current_database() || pg_backend_pid() for
12036 current_setting('max_identifier_length')::int);
12042 -- postgres_fdw.application_name overrides application_name option
12043 -- of a server object if both settings are present.
12044 ALTER SERVER loopback2 OPTIONS (SET application_name 'fdw_wrong');
12045 SET postgres_fdw.application_name TO 'fdw_%a%u%%';
12046 SELECT count(*) FROM remote_application_name
12047 WHERE application_name =
12048 substring('fdw_' || current_setting('application_name') ||
12049 CURRENT_USER || '%' for current_setting('max_identifier_length')::int);
12055 RESET postgres_fdw.application_name;
12056 -- Test %c (session ID) and %C (cluster name) escape sequences.
12057 ALTER SERVER loopback2 OPTIONS (SET application_name 'fdw_%C%c');
12058 SELECT count(*) FROM remote_application_name
12059 WHERE application_name =
12060 substring('fdw_' || current_setting('cluster_name') ||
12061 to_hex(trunc(EXTRACT(EPOCH FROM (SELECT backend_start FROM
12062 pg_stat_get_activity(pg_backend_pid()))))::integer) || '.' ||
12063 to_hex(pg_backend_pid())
12064 for current_setting('max_identifier_length')::int);
12071 DROP FOREIGN TABLE remote_application_name;
12072 DROP VIEW my_application_name;
12073 -- ===================================================================
12074 -- test parallel commit and parallel abort
12075 -- ===================================================================
12076 ALTER SERVER loopback OPTIONS (ADD parallel_commit 'true');
12077 ALTER SERVER loopback OPTIONS (ADD parallel_abort 'true');
12078 ALTER SERVER loopback2 OPTIONS (ADD parallel_commit 'true');
12079 ALTER SERVER loopback2 OPTIONS (ADD parallel_abort 'true');
12080 CREATE TABLE ploc1 (f1 int, f2 text);
12081 CREATE FOREIGN TABLE prem1 (f1 int, f2 text)
12082 SERVER loopback OPTIONS (table_name 'ploc1');
12083 CREATE TABLE ploc2 (f1 int, f2 text);
12084 CREATE FOREIGN TABLE prem2 (f1 int, f2 text)
12085 SERVER loopback2 OPTIONS (table_name 'ploc2');
12087 INSERT INTO prem1 VALUES (101, 'foo');
12088 INSERT INTO prem2 VALUES (201, 'bar');
12090 SELECT * FROM prem1;
12096 SELECT * FROM prem2;
12104 INSERT INTO prem1 VALUES (102, 'foofoo');
12105 INSERT INTO prem2 VALUES (202, 'barbar');
12106 RELEASE SAVEPOINT s;
12108 SELECT * FROM prem1;
12115 SELECT * FROM prem2;
12122 -- This tests executing DEALLOCATE ALL against foreign servers in parallel
12123 -- during pre-commit
12126 INSERT INTO prem1 VALUES (103, 'baz');
12127 INSERT INTO prem2 VALUES (203, 'qux');
12128 ROLLBACK TO SAVEPOINT s;
12129 RELEASE SAVEPOINT s;
12130 INSERT INTO prem1 VALUES (104, 'bazbaz');
12131 INSERT INTO prem2 VALUES (204, 'quxqux');
12133 SELECT * FROM prem1;
12141 SELECT * FROM prem2;
12150 INSERT INTO prem1 VALUES (105, 'test1');
12151 INSERT INTO prem2 VALUES (205, 'test2');
12153 SELECT * FROM prem1;
12161 SELECT * FROM prem2;
12169 -- This tests executing DEALLOCATE ALL against foreign servers in parallel
12170 -- during post-abort
12173 INSERT INTO prem1 VALUES (105, 'test1');
12174 INSERT INTO prem2 VALUES (205, 'test2');
12175 ROLLBACK TO SAVEPOINT s;
12176 RELEASE SAVEPOINT s;
12177 INSERT INTO prem1 VALUES (105, 'test1');
12178 INSERT INTO prem2 VALUES (205, 'test2');
12180 SELECT * FROM prem1;
12188 SELECT * FROM prem2;
12196 ALTER SERVER loopback OPTIONS (DROP parallel_commit);
12197 ALTER SERVER loopback OPTIONS (DROP parallel_abort);
12198 ALTER SERVER loopback2 OPTIONS (DROP parallel_commit);
12199 ALTER SERVER loopback2 OPTIONS (DROP parallel_abort);
12200 -- ===================================================================
12201 -- test for ANALYZE sampling
12202 -- ===================================================================
12203 CREATE TABLE analyze_table (id int, a text, b bigint);
12204 CREATE FOREIGN TABLE analyze_ftable (id int, a text, b bigint)
12205 SERVER loopback OPTIONS (table_name 'analyze_rtable1');
12206 INSERT INTO analyze_table (SELECT x FROM generate_series(1,1000) x);
12207 ANALYZE analyze_table;
12208 SET default_statistics_target = 10;
12209 ANALYZE analyze_table;
12210 ALTER SERVER loopback OPTIONS (analyze_sampling 'invalid');
12211 ERROR: invalid value for string option "analyze_sampling": invalid
12212 ALTER SERVER loopback OPTIONS (analyze_sampling 'auto');
12213 ANALYZE analyze_table;
12214 ALTER SERVER loopback OPTIONS (SET analyze_sampling 'system');
12215 ANALYZE analyze_table;
12216 ALTER SERVER loopback OPTIONS (SET analyze_sampling 'bernoulli');
12217 ANALYZE analyze_table;
12218 ALTER SERVER loopback OPTIONS (SET analyze_sampling 'random');
12219 ANALYZE analyze_table;
12220 ALTER SERVER loopback OPTIONS (SET analyze_sampling 'off');
12221 ANALYZE analyze_table;
12223 DROP FOREIGN TABLE analyze_ftable;
12224 DROP TABLE analyze_table;