1-- ===================================================================
2-- create FDW objects
3-- ===================================================================
4CREATE EXTENSION postgres_fdw;
5CREATE SERVER testserver1 FOREIGN DATA WRAPPER postgres_fdw;
6DO $d$
7    BEGIN
8        EXECUTE $$CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw
9            OPTIONS (dbname '$$||current_database()||$$',
10                     port '$$||current_setting('port')||$$'
11            )$$;
12        EXECUTE $$CREATE SERVER loopback2 FOREIGN DATA WRAPPER postgres_fdw
13            OPTIONS (dbname '$$||current_database()||$$',
14                     port '$$||current_setting('port')||$$'
15            )$$;
16    END;
17$d$;
18CREATE USER MAPPING FOR public SERVER testserver1
19	OPTIONS (user 'value', password 'value');
20CREATE USER MAPPING FOR CURRENT_USER SERVER loopback;
21CREATE USER MAPPING FOR CURRENT_USER SERVER loopback2;
22-- ===================================================================
23-- create objects used through FDW loopback server
24-- ===================================================================
25CREATE TYPE user_enum AS ENUM ('foo', 'bar', 'buz');
26CREATE SCHEMA "S 1";
27CREATE TABLE "S 1"."T 1" (
28	"C 1" int NOT NULL,
29	c2 int NOT NULL,
30	c3 text,
31	c4 timestamptz,
32	c5 timestamp,
33	c6 varchar(10),
34	c7 char(10),
35	c8 user_enum,
36	CONSTRAINT t1_pkey PRIMARY KEY ("C 1")
37);
38CREATE TABLE "S 1"."T 2" (
39	c1 int NOT NULL,
40	c2 text,
41	CONSTRAINT t2_pkey PRIMARY KEY (c1)
42);
43CREATE TABLE "S 1"."T 3" (
44	c1 int NOT NULL,
45	c2 int NOT NULL,
46	c3 text,
47	CONSTRAINT t3_pkey PRIMARY KEY (c1)
48);
49CREATE TABLE "S 1"."T 4" (
50	c1 int NOT NULL,
51	c2 int NOT NULL,
52	c3 text,
53	CONSTRAINT t4_pkey PRIMARY KEY (c1)
54);
55INSERT INTO "S 1"."T 1"
56	SELECT id,
57	       id % 10,
58	       to_char(id, 'FM00000'),
59	       '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval,
60	       '1970-01-01'::timestamp + ((id % 100) || ' days')::interval,
61	       id % 10,
62	       id % 10,
63	       'foo'::user_enum
64	FROM generate_series(1, 1000) id;
65INSERT INTO "S 1"."T 2"
66	SELECT id,
67	       'AAA' || to_char(id, 'FM000')
68	FROM generate_series(1, 100) id;
69INSERT INTO "S 1"."T 3"
70	SELECT id,
71	       id + 1,
72	       'AAA' || to_char(id, 'FM000')
73	FROM generate_series(1, 100) id;
74DELETE FROM "S 1"."T 3" WHERE c1 % 2 != 0;	-- delete for outer join tests
75INSERT INTO "S 1"."T 4"
76	SELECT id,
77	       id + 1,
78	       'AAA' || to_char(id, 'FM000')
79	FROM generate_series(1, 100) id;
80DELETE FROM "S 1"."T 4" WHERE c1 % 3 != 0;	-- delete for outer join tests
81ANALYZE "S 1"."T 1";
82ANALYZE "S 1"."T 2";
83ANALYZE "S 1"."T 3";
84ANALYZE "S 1"."T 4";
85-- ===================================================================
86-- create foreign tables
87-- ===================================================================
88CREATE FOREIGN TABLE ft1 (
89	c0 int,
90	c1 int NOT NULL,
91	c2 int NOT NULL,
92	c3 text,
93	c4 timestamptz,
94	c5 timestamp,
95	c6 varchar(10),
96	c7 char(10) default 'ft1',
97	c8 user_enum
98) SERVER loopback;
99ALTER FOREIGN TABLE ft1 DROP COLUMN c0;
100CREATE FOREIGN TABLE ft2 (
101	c1 int NOT NULL,
102	c2 int NOT NULL,
103	cx int,
104	c3 text,
105	c4 timestamptz,
106	c5 timestamp,
107	c6 varchar(10),
108	c7 char(10) default 'ft2',
109	c8 user_enum
110) SERVER loopback;
111ALTER FOREIGN TABLE ft2 DROP COLUMN cx;
112CREATE FOREIGN TABLE ft4 (
113	c1 int NOT NULL,
114	c2 int NOT NULL,
115	c3 text
116) SERVER loopback OPTIONS (schema_name 'S 1', table_name 'T 3');
117CREATE FOREIGN TABLE ft5 (
118	c1 int NOT NULL,
119	c2 int NOT NULL,
120	c3 text
121) SERVER loopback OPTIONS (schema_name 'S 1', table_name 'T 4');
122CREATE FOREIGN TABLE ft6 (
123	c1 int NOT NULL,
124	c2 int NOT NULL,
125	c3 text
126) SERVER loopback2 OPTIONS (schema_name 'S 1', table_name 'T 4');
127-- ===================================================================
128-- tests for validator
129-- ===================================================================
130-- requiressl and some other parameters are omitted because
131-- valid values for them depend on configure options
132ALTER SERVER testserver1 OPTIONS (
133	use_remote_estimate 'false',
134	updatable 'true',
135	fdw_startup_cost '123.456',
136	fdw_tuple_cost '0.123',
137	service 'value',
138	connect_timeout 'value',
139	dbname 'value',
140	host 'value',
141	hostaddr 'value',
142	port 'value',
143	--client_encoding 'value',
144	application_name 'value',
145	--fallback_application_name 'value',
146	keepalives 'value',
147	keepalives_idle 'value',
148	keepalives_interval 'value',
149	-- requiressl 'value',
150	sslcompression 'value',
151	sslmode 'value',
152	sslcert 'value',
153	sslkey 'value',
154	sslrootcert 'value',
155	sslcrl 'value',
156	--requirepeer 'value',
157	krbsrvname 'value',
158	gsslib 'value'
159	--replication 'value'
160);
161-- Error, invalid list syntax
162ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo; bar');
163ERROR:  parameter "extensions" must be a list of extension names
164-- OK but gets a warning
165ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo, bar');
166WARNING:  extension "foo" is not installed
167WARNING:  extension "bar" is not installed
168ALTER SERVER testserver1 OPTIONS (DROP extensions);
169ALTER USER MAPPING FOR public SERVER testserver1
170	OPTIONS (DROP user, DROP password);
171ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name 'T 1');
172ALTER FOREIGN TABLE ft2 OPTIONS (schema_name 'S 1', table_name 'T 1');
173ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
174ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
175\det+
176                              List of foreign tables
177 Schema | Table |  Server   |              FDW Options              | Description
178--------+-------+-----------+---------------------------------------+-------------
179 public | ft1   | loopback  | (schema_name 'S 1', table_name 'T 1') |
180 public | ft2   | loopback  | (schema_name 'S 1', table_name 'T 1') |
181 public | ft4   | loopback  | (schema_name 'S 1', table_name 'T 3') |
182 public | ft5   | loopback  | (schema_name 'S 1', table_name 'T 4') |
183 public | ft6   | loopback2 | (schema_name 'S 1', table_name 'T 4') |
184(5 rows)
185
186-- Test that alteration of server options causes reconnection
187-- Remote's errors might be non-English, so hide them to ensure stable results
188\set VERBOSITY terse
189SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1;  -- should work
190  c3   |              c4
191-------+------------------------------
192 00001 | Fri Jan 02 00:00:00 1970 PST
193(1 row)
194
195ALTER SERVER loopback OPTIONS (SET dbname 'no such database');
196SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1;  -- should fail
197ERROR:  could not connect to server "loopback"
198DO $d$
199    BEGIN
200        EXECUTE $$ALTER SERVER loopback
201            OPTIONS (SET dbname '$$||current_database()||$$')$$;
202    END;
203$d$;
204SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1;  -- should work again
205  c3   |              c4
206-------+------------------------------
207 00001 | Fri Jan 02 00:00:00 1970 PST
208(1 row)
209
210-- Test that alteration of user mapping options causes reconnection
211ALTER USER MAPPING FOR CURRENT_USER SERVER loopback
212  OPTIONS (ADD user 'no such user');
213SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1;  -- should fail
214ERROR:  could not connect to server "loopback"
215ALTER USER MAPPING FOR CURRENT_USER SERVER loopback
216  OPTIONS (DROP user);
217SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1;  -- should work again
218  c3   |              c4
219-------+------------------------------
220 00001 | Fri Jan 02 00:00:00 1970 PST
221(1 row)
222
223\set VERBOSITY default
224-- Now we should be able to run ANALYZE.
225-- To exercise multiple code paths, we use local stats on ft1
226-- and remote-estimate mode on ft2.
227ANALYZE ft1;
228ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true');
229-- ===================================================================
230-- simple queries
231-- ===================================================================
232-- single table without alias
233EXPLAIN (COSTS OFF) SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
234        QUERY PLAN
235---------------------------
236 Limit
237   ->  Foreign Scan on ft1
238(2 rows)
239
240SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
241 c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
242-----+----+-------+------------------------------+--------------------------+----+------------+-----
243 101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
244 102 |  2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
245 103 |  3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
246 104 |  4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
247 105 |  5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
248 106 |  6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
249 107 |  7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
250 108 |  8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
251 109 |  9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
252 110 |  0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0  | 0          | foo
253(10 rows)
254
255-- single table with alias - also test that tableoid sort is not pushed to remote side
256EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
257                                     QUERY PLAN
258-------------------------------------------------------------------------------------
259 Limit
260   Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
261   ->  Sort
262         Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
263         Sort Key: t1.c3, t1.c1, t1.tableoid
264         ->  Foreign Scan on public.ft1 t1
265               Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
266               Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
267(8 rows)
268
269SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
270 c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
271-----+----+-------+------------------------------+--------------------------+----+------------+-----
272 101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
273 102 |  2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
274 103 |  3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
275 104 |  4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
276 105 |  5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
277 106 |  6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
278 107 |  7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
279 108 |  8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
280 109 |  9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
281 110 |  0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0  | 0          | foo
282(10 rows)
283
284-- whole-row reference
285EXPLAIN (VERBOSE, COSTS OFF) SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
286                                                           QUERY PLAN
287--------------------------------------------------------------------------------------------------------------------------------
288 Limit
289   Output: t1.*, c3, c1
290   ->  Foreign Scan on public.ft1 t1
291         Output: t1.*, c3, c1
292         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
293(5 rows)
294
295SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
296                                             t1
297--------------------------------------------------------------------------------------------
298 (101,1,00101,"Fri Jan 02 00:00:00 1970 PST","Fri Jan 02 00:00:00 1970",1,"1         ",foo)
299 (102,2,00102,"Sat Jan 03 00:00:00 1970 PST","Sat Jan 03 00:00:00 1970",2,"2         ",foo)
300 (103,3,00103,"Sun Jan 04 00:00:00 1970 PST","Sun Jan 04 00:00:00 1970",3,"3         ",foo)
301 (104,4,00104,"Mon Jan 05 00:00:00 1970 PST","Mon Jan 05 00:00:00 1970",4,"4         ",foo)
302 (105,5,00105,"Tue Jan 06 00:00:00 1970 PST","Tue Jan 06 00:00:00 1970",5,"5         ",foo)
303 (106,6,00106,"Wed Jan 07 00:00:00 1970 PST","Wed Jan 07 00:00:00 1970",6,"6         ",foo)
304 (107,7,00107,"Thu Jan 08 00:00:00 1970 PST","Thu Jan 08 00:00:00 1970",7,"7         ",foo)
305 (108,8,00108,"Fri Jan 09 00:00:00 1970 PST","Fri Jan 09 00:00:00 1970",8,"8         ",foo)
306 (109,9,00109,"Sat Jan 10 00:00:00 1970 PST","Sat Jan 10 00:00:00 1970",9,"9         ",foo)
307 (110,0,00110,"Sun Jan 11 00:00:00 1970 PST","Sun Jan 11 00:00:00 1970",0,"0         ",foo)
308(10 rows)
309
310-- empty result
311SELECT * FROM ft1 WHERE false;
312 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
313----+----+----+----+----+----+----+----
314(0 rows)
315
316-- with WHERE clause
317EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1';
318                                                                   QUERY PLAN
319------------------------------------------------------------------------------------------------------------------------------------------------
320 Foreign Scan on public.ft1 t1
321   Output: c1, c2, c3, c4, c5, c6, c7, c8
322   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c7 >= '1'::bpchar)) AND (("C 1" = 101)) AND ((c6 = '1'::text))
323(3 rows)
324
325SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1';
326 c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
327-----+----+-------+------------------------------+--------------------------+----+------------+-----
328 101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
329(1 row)
330
331-- with FOR UPDATE/SHARE
332EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE;
333                                                   QUERY PLAN
334----------------------------------------------------------------------------------------------------------------
335 LockRows
336   Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
337   ->  Foreign Scan on public.ft1 t1
338         Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
339         Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 101)) FOR UPDATE
340(5 rows)
341
342SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE;
343 c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
344-----+----+-------+------------------------------+--------------------------+----+------------+-----
345 101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
346(1 row)
347
348EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE;
349                                                  QUERY PLAN
350---------------------------------------------------------------------------------------------------------------
351 LockRows
352   Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
353   ->  Foreign Scan on public.ft1 t1
354         Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
355         Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 102)) FOR SHARE
356(5 rows)
357
358SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE;
359 c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
360-----+----+-------+------------------------------+--------------------------+----+------------+-----
361 102 |  2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
362(1 row)
363
364-- aggregate
365SELECT COUNT(*) FROM ft1 t1;
366 count
367-------
368  1000
369(1 row)
370
371-- subquery
372SELECT * FROM ft1 t1 WHERE t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 <= 10) ORDER BY c1;
373 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
374----+----+-------+------------------------------+--------------------------+----+------------+-----
375  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
376  2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
377  3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
378  4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
379  5 |  5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
380  6 |  6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
381  7 |  7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
382  8 |  8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
383  9 |  9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
384 10 |  0 | 00010 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0  | 0          | foo
385(10 rows)
386
387-- subquery+MAX
388SELECT * FROM ft1 t1 WHERE t1.c3 = (SELECT MAX(c3) FROM ft2 t2) ORDER BY c1;
389  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
390------+----+-------+------------------------------+--------------------------+----+------------+-----
391 1000 |  0 | 01000 | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0  | 0          | foo
392(1 row)
393
394-- used in CTE
395WITH 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;
396 c1 | c2 |  c3   |              c4
397----+----+-------+------------------------------
398  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST
399  2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST
400  3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST
401  4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST
402  5 |  5 | 00005 | Tue Jan 06 00:00:00 1970 PST
403  6 |  6 | 00006 | Wed Jan 07 00:00:00 1970 PST
404  7 |  7 | 00007 | Thu Jan 08 00:00:00 1970 PST
405  8 |  8 | 00008 | Fri Jan 09 00:00:00 1970 PST
406  9 |  9 | 00009 | Sat Jan 10 00:00:00 1970 PST
407 10 |  0 | 00010 | Sun Jan 11 00:00:00 1970 PST
408(10 rows)
409
410-- fixed values
411SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1;
412 ?column? | ?column?
413----------+----------
414 fixed    |
415(1 row)
416
417-- Test forcing the remote server to produce sorted data for a merge join.
418SET enable_hashjoin TO false;
419SET enable_nestloop TO false;
420-- inner join; expressions in the clauses appear in the equivalence class list
421EXPLAIN (VERBOSE, COSTS OFF)
422	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;
423                                      QUERY PLAN
424---------------------------------------------------------------------------------------
425 Limit
426   Output: t1.c1, t2."C 1"
427   ->  Merge Join
428         Output: t1.c1, t2."C 1"
429         Merge Cond: (t1.c1 = t2."C 1")
430         ->  Foreign Scan on public.ft2 t1
431               Output: t1.c1
432               Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
433         ->  Index Only Scan using t1_pkey on "S 1"."T 1" t2
434               Output: t2."C 1"
435(10 rows)
436
437SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10;
438 c1  | C 1
439-----+-----
440 101 | 101
441 102 | 102
442 103 | 103
443 104 | 104
444 105 | 105
445 106 | 106
446 107 | 107
447 108 | 108
448 109 | 109
449 110 | 110
450(10 rows)
451
452-- outer join; expressions in the clauses do not appear in equivalence class
453-- list but no output change as compared to the previous query
454EXPLAIN (VERBOSE, COSTS OFF)
455	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;
456                                      QUERY PLAN
457---------------------------------------------------------------------------------------
458 Limit
459   Output: t1.c1, t2."C 1"
460   ->  Merge Left Join
461         Output: t1.c1, t2."C 1"
462         Merge Cond: (t1.c1 = t2."C 1")
463         ->  Foreign Scan on public.ft2 t1
464               Output: t1.c1
465               Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
466         ->  Index Only Scan using t1_pkey on "S 1"."T 1" t2
467               Output: t2."C 1"
468(10 rows)
469
470SELECT 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;
471 c1  | C 1
472-----+-----
473 101 | 101
474 102 | 102
475 103 | 103
476 104 | 104
477 105 | 105
478 106 | 106
479 107 | 107
480 108 | 108
481 109 | 109
482 110 | 110
483(10 rows)
484
485-- A join between local table and foreign join. ORDER BY clause is added to the
486-- foreign join so that the local table can be joined using merge join strategy.
487EXPLAIN (VERBOSE, COSTS OFF)
488	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;
489                                                                       QUERY PLAN
490---------------------------------------------------------------------------------------------------------------------------------------------------------
491 Limit
492   Output: t1."C 1"
493   ->  Merge Right Join
494         Output: t1."C 1"
495         Merge Cond: (t3.c1 = t1."C 1")
496         ->  Foreign Scan
497               Output: t3.c1
498               Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
499               Remote SQL: SELECT r3."C 1" FROM ("S 1"."T 1" r2 INNER JOIN "S 1"."T 1" r3 ON (((r2."C 1" = r3."C 1")))) ORDER BY r2."C 1" ASC NULLS LAST
500         ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
501               Output: t1."C 1"
502(11 rows)
503
504SELECT 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;
505 C 1
506-----
507 101
508 102
509 103
510 104
511 105
512 106
513 107
514 108
515 109
516 110
517(10 rows)
518
519-- Test similar to above, except that the full join prevents any equivalence
520-- classes from being merged. This produces single relation equivalence classes
521-- included in join restrictions.
522EXPLAIN (VERBOSE, COSTS OFF)
523	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;
524                                                                            QUERY PLAN
525------------------------------------------------------------------------------------------------------------------------------------------------------------------
526 Limit
527   Output: t1."C 1", t2.c1, t3.c1
528   ->  Merge Right Join
529         Output: t1."C 1", t2.c1, t3.c1
530         Merge Cond: (t3.c1 = t1."C 1")
531         ->  Foreign Scan
532               Output: t3.c1, t2.c1
533               Relations: (public.ft2 t3) LEFT JOIN (public.ft1 t2)
534               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
535         ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
536               Output: t1."C 1"
537(11 rows)
538
539SELECT 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;
540 C 1 | c1  | c1
541-----+-----+-----
542 101 | 101 | 101
543 102 | 102 | 102
544 103 | 103 | 103
545 104 | 104 | 104
546 105 | 105 | 105
547 106 | 106 | 106
548 107 | 107 | 107
549 108 | 108 | 108
550 109 | 109 | 109
551 110 | 110 | 110
552(10 rows)
553
554-- Test similar to above with all full outer joins
555EXPLAIN (VERBOSE, COSTS OFF)
556	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;
557                                                                            QUERY PLAN
558------------------------------------------------------------------------------------------------------------------------------------------------------------------
559 Limit
560   Output: t1."C 1", t2.c1, t3.c1
561   ->  Merge Full Join
562         Output: t1."C 1", t2.c1, t3.c1
563         Merge Cond: (t3.c1 = t1."C 1")
564         ->  Foreign Scan
565               Output: t2.c1, t3.c1
566               Relations: (public.ft1 t2) FULL JOIN (public.ft2 t3)
567               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
568         ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
569               Output: t1."C 1"
570(11 rows)
571
572SELECT 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;
573 C 1 | c1  | c1
574-----+-----+-----
575 101 | 101 | 101
576 102 | 102 | 102
577 103 | 103 | 103
578 104 | 104 | 104
579 105 | 105 | 105
580 106 | 106 | 106
581 107 | 107 | 107
582 108 | 108 | 108
583 109 | 109 | 109
584 110 | 110 | 110
585(10 rows)
586
587RESET enable_hashjoin;
588RESET enable_nestloop;
589-- ===================================================================
590-- WHERE with remotely-executable conditions
591-- ===================================================================
592EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 1;         -- Var, OpExpr(b), Const
593                                         QUERY PLAN
594---------------------------------------------------------------------------------------------
595 Foreign Scan on public.ft1 t1
596   Output: c1, c2, c3, c4, c5, c6, c7, c8
597   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
598(3 rows)
599
600EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 100 AND t1.c2 = 0; -- BoolExpr
601                                                  QUERY PLAN
602--------------------------------------------------------------------------------------------------------------
603 Foreign Scan on public.ft1 t1
604   Output: c1, c2, c3, c4, c5, c6, c7, c8
605   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 100)) AND ((c2 = 0))
606(3 rows)
607
608EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NULL;        -- NullTest
609                                           QUERY PLAN
610-------------------------------------------------------------------------------------------------
611 Foreign Scan on public.ft1 t1
612   Output: c1, c2, c3, c4, c5, c6, c7, c8
613   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" IS NULL))
614(3 rows)
615
616EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL;    -- NullTest
617                                             QUERY PLAN
618-----------------------------------------------------------------------------------------------------
619 Foreign Scan on public.ft1 t1
620   Output: c1, c2, c3, c4, c5, c6, c7, c8
621   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" IS NOT NULL))
622(3 rows)
623
624EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr
625                                                     QUERY PLAN
626---------------------------------------------------------------------------------------------------------------------
627 Foreign Scan on public.ft1 t1
628   Output: c1, c2, c3, c4, c5, c6, c7, c8
629   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))
630(3 rows)
631
632EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1;          -- OpExpr(l)
633                                             QUERY PLAN
634-----------------------------------------------------------------------------------------------------
635 Foreign Scan on public.ft1 t1
636   Output: c1, c2, c3, c4, c5, c6, c7, c8
637   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = (- "C 1")))
638(3 rows)
639
640EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE 1 = c1!;           -- OpExpr(r)
641                                                QUERY PLAN
642----------------------------------------------------------------------------------------------------------
643 Foreign Scan on public.ft1 t1
644   Output: c1, c2, c3, c4, c5, c6, c7, c8
645   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((1::numeric = ("C 1" !)))
646(3 rows)
647
648EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
649                                                                 QUERY PLAN
650--------------------------------------------------------------------------------------------------------------------------------------------
651 Foreign Scan on public.ft1 t1
652   Output: c1, c2, c3, c4, c5, c6, c7, c8
653   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)))
654(3 rows)
655
656EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr
657                                                        QUERY PLAN
658---------------------------------------------------------------------------------------------------------------------------
659 Foreign Scan on public.ft1 t1
660   Output: c1, c2, c3, c4, c5, c6, c7, c8
661   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)])))
662(3 rows)
663
664EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- ArrayRef
665                                                      QUERY PLAN
666----------------------------------------------------------------------------------------------------------------------
667 Foreign Scan on public.ft1 t1
668   Output: c1, c2, c3, c4, c5, c6, c7, c8
669   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])))
670(3 rows)
671
672EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar';  -- check special chars
673                                                 QUERY PLAN
674-------------------------------------------------------------------------------------------------------------
675 Foreign Scan on public.ft1 t1
676   Output: c1, c2, c3, c4, c5, c6, c7, c8
677   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c6 = E'foo''s\\bar'::text))
678(3 rows)
679
680EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c8 = 'foo';  -- can't be sent to remote
681                               QUERY PLAN
682-------------------------------------------------------------------------
683 Foreign Scan on public.ft1 t1
684   Output: c1, c2, c3, c4, c5, c6, c7, c8
685   Filter: (t1.c8 = 'foo'::user_enum)
686   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
687(4 rows)
688
689-- parameterized remote path for foreign table
690EXPLAIN (VERBOSE, COSTS OFF)
691  SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2;
692                                                 QUERY PLAN
693-------------------------------------------------------------------------------------------------------------
694 Nested Loop
695   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
696   ->  Index Scan using t1_pkey on "S 1"."T 1" a
697         Output: a."C 1", a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8
698         Index Cond: (a."C 1" = 47)
699   ->  Foreign Scan on public.ft2 b
700         Output: b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8
701         Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
702(8 rows)
703
704SELECT * FROM ft2 a, ft2 b WHERE a.c1 = 47 AND b.c1 = a.c2;
705 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
706----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----
707 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
708(1 row)
709
710-- check both safe and unsafe join conditions
711EXPLAIN (VERBOSE, COSTS OFF)
712  SELECT * FROM ft2 a, ft2 b
713  WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7);
714                                                 QUERY PLAN
715-------------------------------------------------------------------------------------------------------------
716 Nested Loop
717   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
718   ->  Foreign Scan on public.ft2 a
719         Output: a.c1, a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8
720         Filter: (a.c8 = 'foo'::user_enum)
721         Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c2 = 6))
722   ->  Foreign Scan on public.ft2 b
723         Output: b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8
724         Filter: (upper((a.c7)::text) = (b.c7)::text)
725         Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
726(10 rows)
727
728SELECT * FROM ft2 a, ft2 b
729WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7);
730 c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
731-----+----+-------+------------------------------+--------------------------+----+------------+-----+-----+----+-------+------------------------------+--------------------------+----+------------+-----
732   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
733  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
734  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
735  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
736  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
737  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
738  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
739  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
740  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
741  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
742 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
743 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
744 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
745 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
746 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
747 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
748 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
749 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
750 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
751 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
752 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
753 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
754 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
755 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
756 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
757 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
758 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
759 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
760 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
761 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
762 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
763 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
764 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
765 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
766 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
767 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
768 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
769 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
770 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
771 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
772 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
773 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
774 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
775 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
776 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
777 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
778 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
779 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
780 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
781 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
782 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
783 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
784 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
785 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
786 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
787 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
788 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
789 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
790 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
791 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
792 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
793 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
794 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
795 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
796 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
797 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
798 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
799 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
800 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
801 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
802 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
803 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
804 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
805 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
806 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
807 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
808 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
809 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
810 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
811 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
812 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
813 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
814 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
815 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
816 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
817 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
818 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
819 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
820 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
821 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
822 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
823 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
824 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
825 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
826 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
827 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
828 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
829 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
830 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
831 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
832(100 rows)
833
834-- bug before 9.3.5 due to sloppy handling of remote-estimate parameters
835SELECT * FROM ft1 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft2 WHERE c1 < 5));
836 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
837----+----+-------+------------------------------+--------------------------+----+------------+-----
838  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
839  2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
840  3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
841  4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
842(4 rows)
843
844SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5));
845 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
846----+----+-------+------------------------------+--------------------------+----+------------+-----
847  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
848  2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
849  3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
850  4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
851(4 rows)
852
853-- we should not push order by clause with volatile expressions or unsafe
854-- collations
855EXPLAIN (VERBOSE, COSTS OFF)
856	SELECT * FROM ft2 ORDER BY ft2.c1, random();
857                                  QUERY PLAN
858-------------------------------------------------------------------------------
859 Sort
860   Output: c1, c2, c3, c4, c5, c6, c7, c8, (random())
861   Sort Key: ft2.c1, (random())
862   ->  Foreign Scan on public.ft2
863         Output: c1, c2, c3, c4, c5, c6, c7, c8, random()
864         Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
865(6 rows)
866
867EXPLAIN (VERBOSE, COSTS OFF)
868	SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C";
869                                  QUERY PLAN
870-------------------------------------------------------------------------------
871 Sort
872   Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text)
873   Sort Key: ft2.c1, ft2.c3 COLLATE "C"
874   ->  Foreign Scan on public.ft2
875         Output: c1, c2, c3, c4, c5, c6, c7, c8, c3
876         Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
877(6 rows)
878
879-- user-defined operator/function
880CREATE FUNCTION postgres_fdw_abs(int) RETURNS int AS $$
881BEGIN
882RETURN abs($1);
883END
884$$ LANGUAGE plpgsql IMMUTABLE;
885CREATE OPERATOR === (
886    LEFTARG = int,
887    RIGHTARG = int,
888    PROCEDURE = int4eq,
889    COMMUTATOR = ===
890);
891-- built-in operators and functions can be shipped for remote execution
892EXPLAIN (VERBOSE, COSTS OFF)
893  SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
894                                QUERY PLAN
895--------------------------------------------------------------------------
896 Aggregate
897   Output: count(c3)
898   ->  Foreign Scan on public.ft1 t1
899         Output: c3
900         Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" = abs(c2)))
901(5 rows)
902
903SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
904 count
905-------
906     9
907(1 row)
908
909EXPLAIN (VERBOSE, COSTS OFF)
910  SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
911                             QUERY PLAN
912---------------------------------------------------------------------
913 Aggregate
914   Output: count(c3)
915   ->  Foreign Scan on public.ft1 t1
916         Output: c3
917         Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" = c2))
918(5 rows)
919
920SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
921 count
922-------
923     9
924(1 row)
925
926-- by default, user-defined ones cannot
927EXPLAIN (VERBOSE, COSTS OFF)
928  SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
929                        QUERY PLAN
930-----------------------------------------------------------
931 Aggregate
932   Output: count(c3)
933   ->  Foreign Scan on public.ft1 t1
934         Output: c3
935         Filter: (t1.c1 = postgres_fdw_abs(t1.c2))
936         Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
937(6 rows)
938
939SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
940 count
941-------
942     9
943(1 row)
944
945EXPLAIN (VERBOSE, COSTS OFF)
946  SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
947                        QUERY PLAN
948-----------------------------------------------------------
949 Aggregate
950   Output: count(c3)
951   ->  Foreign Scan on public.ft1 t1
952         Output: c3
953         Filter: (t1.c1 === t1.c2)
954         Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
955(6 rows)
956
957SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
958 count
959-------
960     9
961(1 row)
962
963-- but let's put them in an extension ...
964ALTER EXTENSION postgres_fdw ADD FUNCTION postgres_fdw_abs(int);
965ALTER EXTENSION postgres_fdw ADD OPERATOR === (int, int);
966ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
967-- ... now they can be shipped
968EXPLAIN (VERBOSE, COSTS OFF)
969  SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
970                                          QUERY PLAN
971----------------------------------------------------------------------------------------------
972 Aggregate
973   Output: count(c3)
974   ->  Foreign Scan on public.ft1 t1
975         Output: c3
976         Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" = public.postgres_fdw_abs(c2)))
977(5 rows)
978
979SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
980 count
981-------
982     9
983(1 row)
984
985EXPLAIN (VERBOSE, COSTS OFF)
986  SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
987                                       QUERY PLAN
988----------------------------------------------------------------------------------------
989 Aggregate
990   Output: count(c3)
991   ->  Foreign Scan on public.ft1 t1
992         Output: c3
993         Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2))
994(5 rows)
995
996SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
997 count
998-------
999     9
1000(1 row)
1001
1002-- ===================================================================
1003-- JOIN queries
1004-- ===================================================================
1005-- Analyze ft4 and ft5 so that we have better statistics. These tables do not
1006-- have use_remote_estimate set.
1007ANALYZE ft4;
1008ANALYZE ft5;
1009-- join two tables
1010EXPLAIN (VERBOSE, COSTS OFF)
1011SELECT 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;
1012                                                                                        QUERY PLAN
1013------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1014 Limit
1015   Output: t1.c1, t2.c1, t1.c3
1016   ->  Foreign Scan
1017         Output: t1.c1, t2.c1, t1.c3
1018         Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1019         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 (((r1."C 1" = r2."C 1")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST
1020(6 rows)
1021
1022SELECT 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;
1023 c1  | c1
1024-----+-----
1025 101 | 101
1026 102 | 102
1027 103 | 103
1028 104 | 104
1029 105 | 105
1030 106 | 106
1031 107 | 107
1032 108 | 108
1033 109 | 109
1034 110 | 110
1035(10 rows)
1036
1037-- join three tables
1038EXPLAIN (VERBOSE, COSTS OFF)
1039SELECT 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;
1040                                                                                            QUERY PLAN
1041---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1042 Limit
1043   Output: t1.c1, t2.c2, t3.c3, t1.c3
1044   ->  Sort
1045         Output: t1.c1, t2.c2, t3.c3, t1.c3
1046         Sort Key: t1.c3, t1.c1
1047         ->  Foreign Scan
1048               Output: t1.c1, t2.c2, t3.c3, t1.c3
1049               Relations: ((public.ft1 t1) INNER JOIN (public.ft2 t2)) INNER JOIN (public.ft4 t3)
1050               Remote SQL: SELECT r1."C 1", r1.c3, r2.c2, r4.c3 FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")))) INNER JOIN "S 1"."T 3" r4 ON (((r1."C 1" = r4.c1))))
1051(9 rows)
1052
1053SELECT 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;
1054 c1 | c2 |   c3
1055----+----+--------
1056 22 |  2 | AAA022
1057 24 |  4 | AAA024
1058 26 |  6 | AAA026
1059 28 |  8 | AAA028
1060 30 |  0 | AAA030
1061 32 |  2 | AAA032
1062 34 |  4 | AAA034
1063 36 |  6 | AAA036
1064 38 |  8 | AAA038
1065 40 |  0 | AAA040
1066(10 rows)
1067
1068-- left outer join
1069EXPLAIN (VERBOSE, COSTS OFF)
1070SELECT 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;
1071                                                                            QUERY PLAN
1072-------------------------------------------------------------------------------------------------------------------------------------------------------------------
1073 Limit
1074   Output: t1.c1, t2.c1
1075   ->  Foreign Scan
1076         Output: t1.c1, t2.c1
1077         Relations: (public.ft4 t1) LEFT JOIN (public.ft5 t2)
1078         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
1079(6 rows)
1080
1081SELECT 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;
1082 c1 | c1
1083----+----
1084 22 |
1085 24 | 24
1086 26 |
1087 28 |
1088 30 | 30
1089 32 |
1090 34 |
1091 36 | 36
1092 38 |
1093 40 |
1094(10 rows)
1095
1096-- left outer join three tables
1097EXPLAIN (VERBOSE, COSTS OFF)
1098SELECT 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;
1099                                                                                     QUERY PLAN
1100------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1101 Limit
1102   Output: t1.c1, t2.c2, t3.c3
1103   ->  Foreign Scan
1104         Output: t1.c1, t2.c2, t3.c3
1105         Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
1106         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))))
1107(6 rows)
1108
1109SELECT 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;
1110 c1 | c2 |   c3
1111----+----+--------
1112 11 |  1 |
1113 12 |  2 | AAA012
1114 13 |  3 |
1115 14 |  4 | AAA014
1116 15 |  5 |
1117 16 |  6 | AAA016
1118 17 |  7 |
1119 18 |  8 | AAA018
1120 19 |  9 |
1121 20 |  0 | AAA020
1122(10 rows)
1123
1124-- left outer join + placement of clauses.
1125-- clauses within the nullable side are not pulled up, but top level clause on
1126-- non-nullable side is pushed into non-nullable side
1127EXPLAIN (VERBOSE, COSTS OFF)
1128SELECT 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;
1129                                                                          QUERY PLAN
1130---------------------------------------------------------------------------------------------------------------------------------------------------------------
1131 Foreign Scan
1132   Output: t1.c1, t1.c2, ft5.c1, ft5.c2
1133   Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
1134   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))
1135(4 rows)
1136
1137SELECT 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;
1138 c1 | c2 | c1 | c2
1139----+----+----+----
1140  2 |  3 |    |
1141  4 |  5 |    |
1142  6 |  7 |  6 |  7
1143  8 |  9 |    |
1144(4 rows)
1145
1146-- clauses within the nullable side are not pulled up, but the top level clause
1147-- on nullable side is not pushed down into nullable side
1148EXPLAIN (VERBOSE, COSTS OFF)
1149SELECT 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)
1150			WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
1151                                                                                              QUERY PLAN
1152-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1153 Foreign Scan
1154   Output: t1.c1, t1.c2, ft5.c1, ft5.c2
1155   Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
1156   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))
1157(4 rows)
1158
1159SELECT 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)
1160			WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
1161 c1 | c2 | c1 | c2
1162----+----+----+----
1163  2 |  3 |    |
1164  4 |  5 |    |
1165  6 |  7 |  6 |  7
1166  8 |  9 |    |
1167(4 rows)
1168
1169-- right outer join
1170EXPLAIN (VERBOSE, COSTS OFF)
1171SELECT 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;
1172                                                                            QUERY PLAN
1173-------------------------------------------------------------------------------------------------------------------------------------------------------------------
1174 Limit
1175   Output: t1.c1, t2.c1
1176   ->  Foreign Scan
1177         Output: t1.c1, t2.c1
1178         Relations: (public.ft4 t2) LEFT JOIN (public.ft5 t1)
1179         Remote SQL: SELECT r2.c1, r1.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
1180(6 rows)
1181
1182SELECT 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;
1183 c1 | c1
1184----+----
1185    | 22
1186 24 | 24
1187    | 26
1188    | 28
1189 30 | 30
1190    | 32
1191    | 34
1192 36 | 36
1193    | 38
1194    | 40
1195(10 rows)
1196
1197-- right outer join three tables
1198EXPLAIN (VERBOSE, COSTS OFF)
1199SELECT 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;
1200                                                                                     QUERY PLAN
1201------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1202 Limit
1203   Output: t1.c1, t2.c2, t3.c3
1204   ->  Foreign Scan
1205         Output: t1.c1, t2.c2, t3.c3
1206         Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
1207         Remote SQL: SELECT r4.c3, r2.c2, r1."C 1" 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"))))
1208(6 rows)
1209
1210SELECT 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;
1211 c1 | c2 |   c3
1212----+----+--------
1213 22 |  2 | AAA022
1214 24 |  4 | AAA024
1215 26 |  6 | AAA026
1216 28 |  8 | AAA028
1217 30 |  0 | AAA030
1218 32 |  2 | AAA032
1219 34 |  4 | AAA034
1220 36 |  6 | AAA036
1221 38 |  8 | AAA038
1222 40 |  0 | AAA040
1223(10 rows)
1224
1225-- full outer join
1226EXPLAIN (VERBOSE, COSTS OFF)
1227SELECT 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;
1228                                                                            QUERY PLAN
1229-------------------------------------------------------------------------------------------------------------------------------------------------------------------
1230 Limit
1231   Output: t1.c1, t2.c1
1232   ->  Foreign Scan
1233         Output: t1.c1, t2.c1
1234         Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
1235         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
1236(6 rows)
1237
1238SELECT 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;
1239 c1  | c1
1240-----+----
1241  92 |
1242  94 |
1243  96 | 96
1244  98 |
1245 100 |
1246     |  3
1247     |  9
1248     | 15
1249     | 21
1250     | 27
1251(10 rows)
1252
1253-- full outer join with restrictions on the joining relations
1254EXPLAIN (VERBOSE, COSTS OFF)
1255SELECT 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;
1256                                           QUERY PLAN
1257------------------------------------------------------------------------------------------------
1258 Sort
1259   Output: ft4.c1, ft5.c1
1260   Sort Key: ft4.c1, ft5.c1
1261   ->  Hash Full Join
1262         Output: ft4.c1, ft5.c1
1263         Hash Cond: (ft4.c1 = ft5.c1)
1264         ->  Foreign Scan on public.ft4
1265               Output: ft4.c1, ft4.c2, ft4.c3
1266               Remote SQL: SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))
1267         ->  Hash
1268               Output: ft5.c1
1269               ->  Foreign Scan on public.ft5
1270                     Output: ft5.c1
1271                     Remote SQL: SELECT c1 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))
1272(14 rows)
1273
1274SELECT 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;
1275 c1 | c1
1276----+----
1277 50 |
1278 52 |
1279 54 | 54
1280 56 |
1281 58 |
1282 60 | 60
1283    | 51
1284    | 57
1285(8 rows)
1286
1287-- full outer join + inner join
1288EXPLAIN (VERBOSE, COSTS OFF)
1289SELECT 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;
1290                                                                                                                                           QUERY PLAN
1291-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1292 Limit
1293   Output: t1.c1, t2.c1, t3.c1
1294   ->  Foreign Scan
1295         Output: t1.c1, t2.c1, t3.c1
1296         Relations: ((public.ft4 t1) INNER JOIN (public.ft5 t2)) FULL JOIN (public.ft4 t3)
1297         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
1298(6 rows)
1299
1300SELECT 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;
1301 c1 | c1 | c1
1302----+----+----
1303 52 | 51 |
1304 58 | 57 |
1305    |    |  2
1306    |    |  4
1307    |    |  6
1308    |    |  8
1309    |    | 10
1310    |    | 12
1311    |    | 14
1312    |    | 16
1313(10 rows)
1314
1315-- full outer join three tables
1316EXPLAIN (VERBOSE, COSTS OFF)
1317SELECT 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;
1318                                                                                     QUERY PLAN
1319------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1320 Limit
1321   Output: t1.c1, t2.c2, t3.c3
1322   ->  Foreign Scan
1323         Output: t1.c1, t2.c2, t3.c3
1324         Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
1325         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))))
1326(6 rows)
1327
1328SELECT 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;
1329 c1 | c2 |   c3
1330----+----+--------
1331 11 |  1 |
1332 12 |  2 | AAA012
1333 13 |  3 |
1334 14 |  4 | AAA014
1335 15 |  5 |
1336 16 |  6 | AAA016
1337 17 |  7 |
1338 18 |  8 | AAA018
1339 19 |  9 |
1340 20 |  0 | AAA020
1341(10 rows)
1342
1343-- full outer join + right outer join
1344EXPLAIN (VERBOSE, COSTS OFF)
1345SELECT 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;
1346                                                                                     QUERY PLAN
1347------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1348 Limit
1349   Output: t1.c1, t2.c2, t3.c3
1350   ->  Foreign Scan
1351         Output: t1.c1, t2.c2, t3.c3
1352         Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
1353         Remote SQL: SELECT r4.c3, r2.c2, r1."C 1" 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"))))
1354(6 rows)
1355
1356SELECT 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;
1357 c1 | c2 |   c3
1358----+----+--------
1359 22 |  2 | AAA022
1360 24 |  4 | AAA024
1361 26 |  6 | AAA026
1362 28 |  8 | AAA028
1363 30 |  0 | AAA030
1364 32 |  2 | AAA032
1365 34 |  4 | AAA034
1366 36 |  6 | AAA036
1367 38 |  8 | AAA038
1368 40 |  0 | AAA040
1369(10 rows)
1370
1371-- right outer join + full outer join
1372EXPLAIN (VERBOSE, COSTS OFF)
1373SELECT 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;
1374                                                                                     QUERY PLAN
1375------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1376 Limit
1377   Output: t1.c1, t2.c2, t3.c3
1378   ->  Foreign Scan
1379         Output: t1.c1, t2.c2, t3.c3
1380         Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) FULL JOIN (public.ft4 t3)
1381         Remote SQL: SELECT r2.c2, r1."C 1", 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))))
1382(6 rows)
1383
1384SELECT 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;
1385 c1 | c2 |   c3
1386----+----+--------
1387 11 |  1 |
1388 12 |  2 | AAA012
1389 13 |  3 |
1390 14 |  4 | AAA014
1391 15 |  5 |
1392 16 |  6 | AAA016
1393 17 |  7 |
1394 18 |  8 | AAA018
1395 19 |  9 |
1396 20 |  0 | AAA020
1397(10 rows)
1398
1399-- full outer join + left outer join
1400EXPLAIN (VERBOSE, COSTS OFF)
1401SELECT 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;
1402                                                                                     QUERY PLAN
1403------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1404 Limit
1405   Output: t1.c1, t2.c2, t3.c3
1406   ->  Foreign Scan
1407         Output: t1.c1, t2.c2, t3.c3
1408         Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
1409         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))))
1410(6 rows)
1411
1412SELECT 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;
1413 c1 | c2 |   c3
1414----+----+--------
1415 11 |  1 |
1416 12 |  2 | AAA012
1417 13 |  3 |
1418 14 |  4 | AAA014
1419 15 |  5 |
1420 16 |  6 | AAA016
1421 17 |  7 |
1422 18 |  8 | AAA018
1423 19 |  9 |
1424 20 |  0 | AAA020
1425(10 rows)
1426
1427-- left outer join + full outer join
1428EXPLAIN (VERBOSE, COSTS OFF)
1429SELECT 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;
1430                                                                                     QUERY PLAN
1431------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1432 Limit
1433   Output: t1.c1, t2.c2, t3.c3
1434   ->  Foreign Scan
1435         Output: t1.c1, t2.c2, t3.c3
1436         Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
1437         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))))
1438(6 rows)
1439
1440SELECT 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;
1441 c1 | c2 |   c3
1442----+----+--------
1443 11 |  1 |
1444 12 |  2 | AAA012
1445 13 |  3 |
1446 14 |  4 | AAA014
1447 15 |  5 |
1448 16 |  6 | AAA016
1449 17 |  7 |
1450 18 |  8 | AAA018
1451 19 |  9 |
1452 20 |  0 | AAA020
1453(10 rows)
1454
1455-- right outer join + left outer join
1456EXPLAIN (VERBOSE, COSTS OFF)
1457SELECT 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;
1458                                                                                     QUERY PLAN
1459------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1460 Limit
1461   Output: t1.c1, t2.c2, t3.c3
1462   ->  Foreign Scan
1463         Output: t1.c1, t2.c2, t3.c3
1464         Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) LEFT JOIN (public.ft4 t3)
1465         Remote SQL: SELECT r2.c2, r1."C 1", 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))))
1466(6 rows)
1467
1468SELECT 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;
1469 c1 | c2 |   c3
1470----+----+--------
1471 11 |  1 |
1472 12 |  2 | AAA012
1473 13 |  3 |
1474 14 |  4 | AAA014
1475 15 |  5 |
1476 16 |  6 | AAA016
1477 17 |  7 |
1478 18 |  8 | AAA018
1479 19 |  9 |
1480 20 |  0 | AAA020
1481(10 rows)
1482
1483-- left outer join + right outer join
1484EXPLAIN (VERBOSE, COSTS OFF)
1485SELECT 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;
1486                                                                                     QUERY PLAN
1487-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1488 Limit
1489   Output: t1.c1, t2.c2, t3.c3
1490   ->  Foreign Scan
1491         Output: t1.c1, t2.c2, t3.c3
1492         Relations: (public.ft4 t3) LEFT JOIN ((public.ft2 t1) INNER JOIN (public.ft2 t2))
1493         Remote SQL: SELECT r4.c3, r1."C 1", r2.c2 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))))
1494(6 rows)
1495
1496SELECT 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;
1497 c1 | c2 |   c3
1498----+----+--------
1499 22 |  2 | AAA022
1500 24 |  4 | AAA024
1501 26 |  6 | AAA026
1502 28 |  8 | AAA028
1503 30 |  0 | AAA030
1504 32 |  2 | AAA032
1505 34 |  4 | AAA034
1506 36 |  6 | AAA036
1507 38 |  8 | AAA038
1508 40 |  0 | AAA040
1509(10 rows)
1510
1511-- full outer join + WHERE clause, only matched rows
1512EXPLAIN (VERBOSE, COSTS OFF)
1513SELECT 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;
1514                                                                            QUERY PLAN
1515------------------------------------------------------------------------------------------------------------------------------------------------------------------
1516 Limit
1517   Output: t1.c1, t2.c1
1518   ->  Sort
1519         Output: t1.c1, t2.c1
1520         Sort Key: t1.c1, t2.c1
1521         ->  Foreign Scan
1522               Output: t1.c1, t2.c1
1523               Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
1524               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)))
1525(9 rows)
1526
1527SELECT 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;
1528 c1 | c1
1529----+----
1530 66 | 66
1531 72 | 72
1532 78 | 78
1533 84 | 84
1534 90 | 90
1535 96 | 96
1536    |  3
1537    |  9
1538    | 15
1539    | 21
1540(10 rows)
1541
1542-- full outer join + WHERE clause with shippable extensions set
1543EXPLAIN (VERBOSE, COSTS OFF)
1544SELECT 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;
1545                                                                                  QUERY PLAN
1546-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1547 Limit
1548   Output: t1.c1, t2.c2, t1.c3
1549   ->  Foreign Scan
1550         Output: t1.c1, t2.c2, t1.c3
1551         Relations: (public.ft1 t1) FULL JOIN (public.ft2 t2)
1552         Remote SQL: SELECT r1."C 1", r1.c3, r2.c2 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))
1553(6 rows)
1554
1555ALTER SERVER loopback OPTIONS (DROP extensions);
1556-- full outer join + WHERE clause with shippable extensions not set
1557EXPLAIN (VERBOSE, COSTS OFF)
1558SELECT 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;
1559                                                          QUERY PLAN
1560-------------------------------------------------------------------------------------------------------------------------------
1561 Limit
1562   Output: t1.c1, t2.c2, t1.c3
1563   ->  Foreign Scan
1564         Output: t1.c1, t2.c2, t1.c3
1565         Filter: (postgres_fdw_abs(t1.c1) > 0)
1566         Relations: (public.ft1 t1) FULL JOIN (public.ft2 t2)
1567         Remote SQL: SELECT r1."C 1", r1.c3, r2.c2 FROM ("S 1"."T 1" r1 FULL JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
1568(7 rows)
1569
1570ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
1571-- join two tables with FOR UPDATE clause
1572-- tests whole-row reference for row marks
1573EXPLAIN (VERBOSE, COSTS OFF)
1574SELECT 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;
1575                                                                                                                                                                                                               QUERY PLAN
1576-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1577 Limit
1578   Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1579   ->  LockRows
1580         Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1581         ->  Foreign Scan
1582               Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1583               Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1584               Remote SQL: SELECT r1."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, r2."C 1", 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")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR UPDATE OF r1
1585               ->  Sort
1586                     Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1587                     Sort Key: t1.c3, t1.c1
1588                     ->  Merge Join
1589                           Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1590                           Merge Cond: (t1.c1 = t2.c1)
1591                           ->  Sort
1592                                 Output: t1.c1, t1.c3, t1.*
1593                                 Sort Key: t1.c1
1594                                 ->  Foreign Scan on public.ft1 t1
1595                                       Output: t1.c1, t1.c3, t1.*
1596                                       Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
1597                           ->  Sort
1598                                 Output: t2.c1, t2.*
1599                                 Sort Key: t2.c1
1600                                 ->  Foreign Scan on public.ft2 t2
1601                                       Output: t2.c1, t2.*
1602                                       Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1603(26 rows)
1604
1605SELECT 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;
1606 c1  | c1
1607-----+-----
1608 101 | 101
1609 102 | 102
1610 103 | 103
1611 104 | 104
1612 105 | 105
1613 106 | 106
1614 107 | 107
1615 108 | 108
1616 109 | 109
1617 110 | 110
1618(10 rows)
1619
1620EXPLAIN (VERBOSE, COSTS OFF)
1621SELECT 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;
1622                                                                                                                                                                                                                        QUERY PLAN
1623----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1624 Limit
1625   Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1626   ->  LockRows
1627         Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1628         ->  Foreign Scan
1629               Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1630               Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1631               Remote SQL: SELECT r1."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, r2."C 1", 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")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR UPDATE OF r1 FOR UPDATE OF r2
1632               ->  Sort
1633                     Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1634                     Sort Key: t1.c3, t1.c1
1635                     ->  Merge Join
1636                           Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1637                           Merge Cond: (t1.c1 = t2.c1)
1638                           ->  Sort
1639                                 Output: t1.c1, t1.c3, t1.*
1640                                 Sort Key: t1.c1
1641                                 ->  Foreign Scan on public.ft1 t1
1642                                       Output: t1.c1, t1.c3, t1.*
1643                                       Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
1644                           ->  Sort
1645                                 Output: t2.c1, t2.*
1646                                 Sort Key: t2.c1
1647                                 ->  Foreign Scan on public.ft2 t2
1648                                       Output: t2.c1, t2.*
1649                                       Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
1650(26 rows)
1651
1652SELECT 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;
1653 c1  | c1
1654-----+-----
1655 101 | 101
1656 102 | 102
1657 103 | 103
1658 104 | 104
1659 105 | 105
1660 106 | 106
1661 107 | 107
1662 108 | 108
1663 109 | 109
1664 110 | 110
1665(10 rows)
1666
1667-- join two tables with FOR SHARE clause
1668EXPLAIN (VERBOSE, COSTS OFF)
1669SELECT 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;
1670                                                                                                                                                                                                               QUERY PLAN
1671----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1672 Limit
1673   Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1674   ->  LockRows
1675         Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1676         ->  Foreign Scan
1677               Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1678               Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1679               Remote SQL: SELECT r1."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, r2."C 1", 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")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR SHARE OF r1
1680               ->  Sort
1681                     Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1682                     Sort Key: t1.c3, t1.c1
1683                     ->  Merge Join
1684                           Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1685                           Merge Cond: (t1.c1 = t2.c1)
1686                           ->  Sort
1687                                 Output: t1.c1, t1.c3, t1.*
1688                                 Sort Key: t1.c1
1689                                 ->  Foreign Scan on public.ft1 t1
1690                                       Output: t1.c1, t1.c3, t1.*
1691                                       Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
1692                           ->  Sort
1693                                 Output: t2.c1, t2.*
1694                                 Sort Key: t2.c1
1695                                 ->  Foreign Scan on public.ft2 t2
1696                                       Output: t2.c1, t2.*
1697                                       Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1698(26 rows)
1699
1700SELECT 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;
1701 c1  | c1
1702-----+-----
1703 101 | 101
1704 102 | 102
1705 103 | 103
1706 104 | 104
1707 105 | 105
1708 106 | 106
1709 107 | 107
1710 108 | 108
1711 109 | 109
1712 110 | 110
1713(10 rows)
1714
1715EXPLAIN (VERBOSE, COSTS OFF)
1716SELECT 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;
1717                                                                                                                                                                                                                       QUERY PLAN
1718--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1719 Limit
1720   Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1721   ->  LockRows
1722         Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1723         ->  Foreign Scan
1724               Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1725               Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1726               Remote SQL: SELECT r1."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, r2."C 1", 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")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST FOR SHARE OF r1 FOR SHARE OF r2
1727               ->  Sort
1728                     Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1729                     Sort Key: t1.c3, t1.c1
1730                     ->  Merge Join
1731                           Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1732                           Merge Cond: (t1.c1 = t2.c1)
1733                           ->  Sort
1734                                 Output: t1.c1, t1.c3, t1.*
1735                                 Sort Key: t1.c1
1736                                 ->  Foreign Scan on public.ft1 t1
1737                                       Output: t1.c1, t1.c3, t1.*
1738                                       Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
1739                           ->  Sort
1740                                 Output: t2.c1, t2.*
1741                                 Sort Key: t2.c1
1742                                 ->  Foreign Scan on public.ft2 t2
1743                                       Output: t2.c1, t2.*
1744                                       Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
1745(26 rows)
1746
1747SELECT 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;
1748 c1  | c1
1749-----+-----
1750 101 | 101
1751 102 | 102
1752 103 | 103
1753 104 | 104
1754 105 | 105
1755 106 | 106
1756 107 | 107
1757 108 | 108
1758 109 | 109
1759 110 | 110
1760(10 rows)
1761
1762-- join in CTE
1763EXPLAIN (VERBOSE, COSTS OFF)
1764WITH t (c1_1, c1_3, c2_1) AS (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;
1765                                                             QUERY PLAN
1766-------------------------------------------------------------------------------------------------------------------------------------
1767 Limit
1768   Output: t.c1_1, t.c2_1, t.c1_3
1769   CTE t
1770     ->  Foreign Scan
1771           Output: t1.c1, t1.c3, t2.c1
1772           Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1773           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 (((r1."C 1" = r2."C 1"))))
1774   ->  Sort
1775         Output: t.c1_1, t.c2_1, t.c1_3
1776         Sort Key: t.c1_3, t.c1_1
1777         ->  CTE Scan on t
1778               Output: t.c1_1, t.c2_1, t.c1_3
1779(12 rows)
1780
1781WITH t (c1_1, c1_3, c2_1) AS (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;
1782 c1_1 | c2_1
1783------+------
1784  101 |  101
1785  102 |  102
1786  103 |  103
1787  104 |  104
1788  105 |  105
1789  106 |  106
1790  107 |  107
1791  108 |  108
1792  109 |  109
1793  110 |  110
1794(10 rows)
1795
1796-- ctid with whole-row reference
1797EXPLAIN (VERBOSE, COSTS OFF)
1798SELECT 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;
1799                                                                                                                                                                                                   QUERY PLAN
1800-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1801 Limit
1802   Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
1803   ->  Foreign Scan
1804         Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
1805         Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1806         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, r1."C 1", r1.c3, 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")))) ORDER BY r1.c3 ASC NULLS LAST, r1."C 1" ASC NULLS LAST
1807(6 rows)
1808
1809-- SEMI JOIN, not pushed down
1810EXPLAIN (VERBOSE, COSTS OFF)
1811SELECT 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;
1812                                         QUERY PLAN
1813---------------------------------------------------------------------------------------------
1814 Limit
1815   Output: t1.c1
1816   ->  Merge Semi Join
1817         Output: t1.c1
1818         Merge Cond: (t1.c1 = t2.c1)
1819         ->  Foreign Scan on public.ft1 t1
1820               Output: t1.c1
1821               Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1822         ->  Materialize
1823               Output: t2.c1
1824               ->  Foreign Scan on public.ft2 t2
1825                     Output: t2.c1
1826                     Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1827(13 rows)
1828
1829SELECT 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;
1830 c1
1831-----
1832 101
1833 102
1834 103
1835 104
1836 105
1837 106
1838 107
1839 108
1840 109
1841 110
1842(10 rows)
1843
1844-- ANTI JOIN, not pushed down
1845EXPLAIN (VERBOSE, COSTS OFF)
1846SELECT 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;
1847                                      QUERY PLAN
1848---------------------------------------------------------------------------------------
1849 Limit
1850   Output: t1.c1
1851   ->  Merge Anti Join
1852         Output: t1.c1
1853         Merge Cond: (t1.c1 = t2.c2)
1854         ->  Foreign Scan on public.ft1 t1
1855               Output: t1.c1
1856               Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1857         ->  Materialize
1858               Output: t2.c2
1859               ->  Foreign Scan on public.ft2 t2
1860                     Output: t2.c2
1861                     Remote SQL: SELECT c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
1862(13 rows)
1863
1864SELECT 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;
1865 c1
1866-----
1867 110
1868 111
1869 112
1870 113
1871 114
1872 115
1873 116
1874 117
1875 118
1876 119
1877(10 rows)
1878
1879-- CROSS JOIN, not pushed down
1880EXPLAIN (VERBOSE, COSTS OFF)
1881SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
1882                             QUERY PLAN
1883---------------------------------------------------------------------
1884 Limit
1885   Output: t1.c1, t2.c1
1886   ->  Sort
1887         Output: t1.c1, t2.c1
1888         Sort Key: t1.c1, t2.c1
1889         ->  Nested Loop
1890               Output: t1.c1, t2.c1
1891               ->  Foreign Scan on public.ft1 t1
1892                     Output: t1.c1
1893                     Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
1894               ->  Materialize
1895                     Output: t2.c1
1896                     ->  Foreign Scan on public.ft2 t2
1897                           Output: t2.c1
1898                           Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
1899(15 rows)
1900
1901SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
1902 c1 | c1
1903----+-----
1904  1 | 101
1905  1 | 102
1906  1 | 103
1907  1 | 104
1908  1 | 105
1909  1 | 106
1910  1 | 107
1911  1 | 108
1912  1 | 109
1913  1 | 110
1914(10 rows)
1915
1916-- different server, not pushed down. No result expected.
1917EXPLAIN (VERBOSE, COSTS OFF)
1918SELECT 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;
1919                                      QUERY PLAN
1920---------------------------------------------------------------------------------------
1921 Limit
1922   Output: t1.c1, t2.c1
1923   ->  Merge Join
1924         Output: t1.c1, t2.c1
1925         Merge Cond: (t2.c1 = t1.c1)
1926         ->  Foreign Scan on public.ft6 t2
1927               Output: t2.c1, t2.c2, t2.c3
1928               Remote SQL: SELECT c1 FROM "S 1"."T 4" ORDER BY c1 ASC NULLS LAST
1929         ->  Materialize
1930               Output: t1.c1, t1.c2, t1.c3
1931               ->  Foreign Scan on public.ft5 t1
1932                     Output: t1.c1, t1.c2, t1.c3
1933                     Remote SQL: SELECT c1 FROM "S 1"."T 4" ORDER BY c1 ASC NULLS LAST
1934(13 rows)
1935
1936SELECT 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;
1937 c1 | c1
1938----+----
1939(0 rows)
1940
1941-- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS
1942-- JOIN since c8 in both tables has same value.
1943EXPLAIN (VERBOSE, COSTS OFF)
1944SELECT 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;
1945                               QUERY PLAN
1946-------------------------------------------------------------------------
1947 Limit
1948   Output: t1.c1, t2.c1
1949   ->  Sort
1950         Output: t1.c1, t2.c1
1951         Sort Key: t1.c1, t2.c1
1952         ->  Merge Left Join
1953               Output: t1.c1, t2.c1
1954               Merge Cond: (t1.c8 = t2.c8)
1955               ->  Sort
1956                     Output: t1.c1, t1.c8
1957                     Sort Key: t1.c8
1958                     ->  Foreign Scan on public.ft1 t1
1959                           Output: t1.c1, t1.c8
1960                           Remote SQL: SELECT "C 1", c8 FROM "S 1"."T 1"
1961               ->  Sort
1962                     Output: t2.c1, t2.c8
1963                     Sort Key: t2.c8
1964                     ->  Foreign Scan on public.ft2 t2
1965                           Output: t2.c1, t2.c8
1966                           Remote SQL: SELECT "C 1", c8 FROM "S 1"."T 1"
1967(20 rows)
1968
1969SELECT 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;
1970 c1 | c1
1971----+-----
1972  1 | 101
1973  1 | 102
1974  1 | 103
1975  1 | 104
1976  1 | 105
1977  1 | 106
1978  1 | 107
1979  1 | 108
1980  1 | 109
1981  1 | 110
1982(10 rows)
1983
1984-- unsafe conditions on one side (c8 has a UDT), not pushed down.
1985EXPLAIN (VERBOSE, COSTS OFF)
1986SELECT 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;
1987                                 QUERY PLAN
1988-----------------------------------------------------------------------------
1989 Limit
1990   Output: t1.c1, t2.c1, t1.c3
1991   ->  Sort
1992         Output: t1.c1, t2.c1, t1.c3
1993         Sort Key: t1.c3, t1.c1
1994         ->  Hash Right Join
1995               Output: t1.c1, t2.c1, t1.c3
1996               Hash Cond: (t2.c1 = t1.c1)
1997               ->  Foreign Scan on public.ft2 t2
1998                     Output: t2.c1
1999                     Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2000               ->  Hash
2001                     Output: t1.c1, t1.c3
2002                     ->  Foreign Scan on public.ft1 t1
2003                           Output: t1.c1, t1.c3
2004                           Filter: (t1.c8 = 'foo'::user_enum)
2005                           Remote SQL: SELECT "C 1", c3, c8 FROM "S 1"."T 1"
2006(17 rows)
2007
2008SELECT 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;
2009 c1  | c1
2010-----+-----
2011 101 | 101
2012 102 | 102
2013 103 | 103
2014 104 | 104
2015 105 | 105
2016 106 | 106
2017 107 | 107
2018 108 | 108
2019 109 | 109
2020 110 | 110
2021(10 rows)
2022
2023-- join where unsafe to pushdown condition in WHERE clause has a column not
2024-- in the SELECT clause. In this test unsafe clause needs to have column
2025-- references from both joining sides so that the clause is not pushed down
2026-- into one of the joining sides.
2027EXPLAIN (VERBOSE, COSTS OFF)
2028SELECT 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;
2029                                                                      QUERY PLAN
2030-------------------------------------------------------------------------------------------------------------------------------------------------------
2031 Limit
2032   Output: t1.c1, t2.c1, t1.c3
2033   ->  Sort
2034         Output: t1.c1, t2.c1, t1.c3
2035         Sort Key: t1.c3, t1.c1
2036         ->  Foreign Scan
2037               Output: t1.c1, t2.c1, t1.c3
2038               Filter: (t1.c8 = t2.c8)
2039               Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2040               Remote SQL: SELECT r1."C 1", r1.c3, r2."C 1", r1.c8, r2.c8 FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
2041(10 rows)
2042
2043SELECT 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;
2044 c1  | c1
2045-----+-----
2046 101 | 101
2047 102 | 102
2048 103 | 103
2049 104 | 104
2050 105 | 105
2051 106 | 106
2052 107 | 107
2053 108 | 108
2054 109 | 109
2055 110 | 110
2056(10 rows)
2057
2058-- Aggregate after UNION, for testing setrefs
2059EXPLAIN (VERBOSE, COSTS OFF)
2060SELECT 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;
2061                                                                     QUERY PLAN
2062----------------------------------------------------------------------------------------------------------------------------------------------------
2063 Limit
2064   Output: t1.c1, (avg((t1.c1 + t2.c1)))
2065   ->  Sort
2066         Output: t1.c1, (avg((t1.c1 + t2.c1)))
2067         Sort Key: t1.c1
2068         ->  HashAggregate
2069               Output: t1.c1, avg((t1.c1 + t2.c1))
2070               Group Key: t1.c1
2071               ->  HashAggregate
2072                     Output: t1.c1, t2.c1
2073                     Group Key: t1.c1, t2.c1
2074                     ->  Append
2075                           ->  Foreign Scan
2076                                 Output: t1.c1, t2.c1
2077                                 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2078                                 Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
2079                           ->  Foreign Scan
2080                                 Output: t1_1.c1, t2_1.c1
2081                                 Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2082                                 Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1"))))
2083(20 rows)
2084
2085SELECT 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;
2086 t1c1 |         avg
2087------+----------------------
2088  101 | 202.0000000000000000
2089  102 | 204.0000000000000000
2090  103 | 206.0000000000000000
2091  104 | 208.0000000000000000
2092  105 | 210.0000000000000000
2093  106 | 212.0000000000000000
2094  107 | 214.0000000000000000
2095  108 | 216.0000000000000000
2096  109 | 218.0000000000000000
2097  110 | 220.0000000000000000
2098(10 rows)
2099
2100-- join with lateral reference
2101EXPLAIN (VERBOSE, COSTS OFF)
2102SELECT 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;
2103                                                                             QUERY PLAN
2104--------------------------------------------------------------------------------------------------------------------------------------------------------------------
2105 Limit
2106   Output: t1."C 1"
2107   ->  Nested Loop
2108         Output: t1."C 1"
2109         ->  Index Scan using t1_pkey on "S 1"."T 1" t1
2110               Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
2111         ->  HashAggregate
2112               Output: t2.c1, t3.c1
2113               Group Key: t2.c1, t3.c1
2114               ->  Foreign Scan
2115                     Output: t2.c1, t3.c1
2116                     Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
2117                     Remote SQL: SELECT r1."C 1", r2."C 1" FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1."C 1" = r2."C 1")) AND ((r1.c2 = $1::integer))))
2118(13 rows)
2119
2120SELECT 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;
2121 C 1
2122-----
2123   1
2124   1
2125   1
2126   1
2127   1
2128   1
2129   1
2130   1
2131   1
2132   1
2133(10 rows)
2134
2135-- bug #15613: bad plan for foreign table scan with lateral reference
2136EXPLAIN (VERBOSE, COSTS OFF)
2137SELECT ref_0.c2, subq_1.*
2138FROM
2139    "S 1"."T 1" AS ref_0,
2140    LATERAL (
2141        SELECT ref_0."C 1" c1, subq_0.*
2142        FROM (SELECT ref_0.c2, ref_1.c3
2143              FROM ft1 AS ref_1) AS subq_0
2144             RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3)
2145    ) AS subq_1
2146WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001'
2147ORDER BY ref_0."C 1";
2148                                               QUERY PLAN
2149---------------------------------------------------------------------------------------------------------
2150 Nested Loop
2151   Output: ref_0.c2, ref_0."C 1", (ref_0.c2), ref_1.c3, ref_0."C 1"
2152   ->  Nested Loop
2153         Output: ref_0.c2, ref_0."C 1", ref_1.c3, (ref_0.c2)
2154         ->  Index Scan using t1_pkey on "S 1"."T 1" ref_0
2155               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
2156               Index Cond: (ref_0."C 1" < 10)
2157         ->  Foreign Scan on public.ft1 ref_1
2158               Output: ref_1.c3, ref_0.c2
2159               Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE ((c3 = '00001'::text))
2160   ->  Materialize
2161         Output: ref_3.c3
2162         ->  Foreign Scan on public.ft2 ref_3
2163               Output: ref_3.c3
2164               Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE ((c3 = '00001'::text))
2165(15 rows)
2166
2167SELECT ref_0.c2, subq_1.*
2168FROM
2169    "S 1"."T 1" AS ref_0,
2170    LATERAL (
2171        SELECT ref_0."C 1" c1, subq_0.*
2172        FROM (SELECT ref_0.c2, ref_1.c3
2173              FROM ft1 AS ref_1) AS subq_0
2174             RIGHT JOIN ft2 AS ref_3 ON (subq_0.c3 = ref_3.c3)
2175    ) AS subq_1
2176WHERE ref_0."C 1" < 10 AND subq_1.c3 = '00001'
2177ORDER BY ref_0."C 1";
2178 c2 | c1 | c2 |  c3
2179----+----+----+-------
2180  1 |  1 |  1 | 00001
2181  2 |  2 |  2 | 00001
2182  3 |  3 |  3 | 00001
2183  4 |  4 |  4 | 00001
2184  5 |  5 |  5 | 00001
2185  6 |  6 |  6 | 00001
2186  7 |  7 |  7 | 00001
2187  8 |  8 |  8 | 00001
2188  9 |  9 |  9 | 00001
2189(9 rows)
2190
2191-- non-Var items in targetlist of the nullable rel of a join preventing
2192-- push-down in some cases
2193-- unable to push {ft1, ft2}
2194EXPLAIN (VERBOSE, COSTS OFF)
2195SELECT 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;
2196                                                        QUERY PLAN
2197---------------------------------------------------------------------------------------------------------------------------
2198 Nested Loop Left Join
2199   Output: (13), ft2.c1
2200   Join Filter: (13 = ft2.c1)
2201   ->  Foreign Scan on public.ft2
2202         Output: ft2.c1
2203         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
2204   ->  Materialize
2205         Output: (13)
2206         ->  Foreign Scan on public.ft1
2207               Output: 13
2208               Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE (("C 1" = 13))
2209(11 rows)
2210
2211SELECT 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;
2212 a  | c1
2213----+----
2214    | 10
2215    | 11
2216    | 12
2217 13 | 13
2218    | 14
2219    | 15
2220(6 rows)
2221
2222-- ok to push {ft1, ft2} but not {ft1, ft2, ft4}
2223EXPLAIN (VERBOSE, COSTS OFF)
2224SELECT 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;
2225                                                                                    QUERY PLAN
2226-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2227 Nested Loop Left Join
2228   Output: ft4.c1, (13), ft1.c1, ft2.c1
2229   Join Filter: (ft4.c1 = ft1.c1)
2230   ->  Foreign Scan on public.ft4
2231         Output: ft4.c1, ft4.c2, ft4.c3
2232         Remote SQL: SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 10)) AND ((c1 <= 15))
2233   ->  Materialize
2234         Output: ft1.c1, ft2.c1, (13)
2235         ->  Foreign Scan
2236               Output: ft1.c1, ft2.c1, 13
2237               Relations: (public.ft1) INNER JOIN (public.ft2)
2238               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
2239(12 rows)
2240
2241SELECT 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;
2242 c1 | a  | b  | c
2243----+----+----+----
2244 10 |    |    |
2245 12 | 13 | 12 | 12
2246 14 |    |    |
2247(3 rows)
2248
2249-- join with nullable side with some columns with null values
2250UPDATE ft5 SET c3 = null where c1 % 9 = 0;
2251EXPLAIN (VERBOSE, COSTS OFF)
2252SELECT 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;
2253                                                                                                                                QUERY PLAN
2254---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2255 Foreign Scan
2256   Output: ft5.*, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2
2257   Relations: (public.ft5) INNER JOIN (public.ft4)
2258   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
2259(4 rows)
2260
2261SELECT 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;
2262      ft5       | c1 | c2 |   c3   | c1 | c2
2263----------------+----+----+--------+----+----
2264 (12,13,AAA012) | 12 | 13 | AAA012 | 12 | 13
2265 (18,19,)       | 18 | 19 |        | 18 | 19
2266 (24,25,AAA024) | 24 | 25 | AAA024 | 24 | 25
2267 (30,31,AAA030) | 30 | 31 | AAA030 | 30 | 31
2268(4 rows)
2269
2270-- multi-way join involving multiple merge joins
2271-- (this case used to have EPQ-related planning problems)
2272SET enable_nestloop TO false;
2273SET enable_hashjoin TO false;
2274EXPLAIN (VERBOSE, COSTS OFF)
2275SELECT * FROM ft1, ft2, ft4, ft5 WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1
2276    AND ft1.c2 = ft5.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE;
2277                                                                                                                                                                                                                                                                                                                                                                                                                             QUERY PLAN
2278--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2279 LockRows
2280   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, ft1.*, ft2.*, ft4.*, ft5.*
2281   ->  Foreign Scan
2282         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, ft1.*, ft2.*, ft4.*, ft5.*
2283         Relations: (((public.ft1) INNER JOIN (public.ft2)) INNER JOIN (public.ft4)) INNER JOIN (public.ft5)
2284         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 (((r1."C 1" = r2."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)))) FOR UPDATE OF r1 FOR UPDATE OF r2 FOR UPDATE OF r3 FOR UPDATE OF r4
2285         ->  Merge Join
2286               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.*
2287               Merge Cond: (ft1.c2 = ft5.c1)
2288               ->  Merge Join
2289                     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.*
2290                     Merge Cond: (ft1.c2 = ft4.c1)
2291                     ->  Sort
2292                           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.*
2293                           Sort Key: ft1.c2
2294                           ->  Merge Join
2295                                 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.*
2296                                 Merge Cond: (ft1.c1 = ft2.c1)
2297                                 ->  Sort
2298                                       Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2299                                       Sort Key: ft1.c1
2300                                       ->  Foreign Scan on public.ft1
2301                                             Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2302                                             Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 100)) FOR UPDATE
2303                                 ->  Materialize
2304                                       Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*
2305                                       ->  Foreign Scan on public.ft2
2306                                             Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*
2307                                             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
2308                     ->  Sort
2309                           Output: ft4.c1, ft4.c2, ft4.c3, ft4.*
2310                           Sort Key: ft4.c1
2311                           ->  Foreign Scan on public.ft4
2312                                 Output: ft4.c1, ft4.c2, ft4.c3, ft4.*
2313                                 Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3" FOR UPDATE
2314               ->  Sort
2315                     Output: ft5.c1, ft5.c2, ft5.c3, ft5.*
2316                     Sort Key: ft5.c1
2317                     ->  Foreign Scan on public.ft5
2318                           Output: ft5.c1, ft5.c2, ft5.c3, ft5.*
2319                           Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4" FOR UPDATE
2320(41 rows)
2321
2322SELECT * FROM ft1, ft2, ft4, ft5 WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1
2323    AND ft1.c2 = ft5.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE;
2324 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1 | c2 |   c3   | c1 | c2 |   c3
2325----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------+----+----+--------
2326  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
2327 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
2328 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
2329 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
2330 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
2331 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
2332 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
2333 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
2334 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
2335 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
2336(10 rows)
2337
2338RESET enable_nestloop;
2339RESET enable_hashjoin;
2340-- check join pushdown in situations where multiple userids are involved
2341CREATE ROLE regress_view_owner;
2342CREATE USER MAPPING FOR regress_view_owner SERVER loopback;
2343GRANT SELECT ON ft4 TO regress_view_owner;
2344GRANT SELECT ON ft5 TO regress_view_owner;
2345CREATE VIEW v4 AS SELECT * FROM ft4;
2346CREATE VIEW v5 AS SELECT * FROM ft5;
2347ALTER VIEW v5 OWNER TO regress_view_owner;
2348EXPLAIN (VERBOSE, COSTS OFF)
2349SELECT 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
2350                              QUERY PLAN
2351----------------------------------------------------------------------
2352 Limit
2353   Output: ft4.c1, ft5.c2, ft5.c1
2354   ->  Sort
2355         Output: ft4.c1, ft5.c2, ft5.c1
2356         Sort Key: ft4.c1, ft5.c1
2357         ->  Hash Left Join
2358               Output: ft4.c1, ft5.c2, ft5.c1
2359               Hash Cond: (ft4.c1 = ft5.c1)
2360               ->  Foreign Scan on public.ft4
2361                     Output: ft4.c1, ft4.c2, ft4.c3
2362                     Remote SQL: SELECT c1 FROM "S 1"."T 3"
2363               ->  Hash
2364                     Output: ft5.c2, ft5.c1
2365                     ->  Foreign Scan on public.ft5
2366                           Output: ft5.c2, ft5.c1
2367                           Remote SQL: SELECT c1, c2 FROM "S 1"."T 4"
2368(16 rows)
2369
2370SELECT 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;
2371 c1 | c2
2372----+----
2373 22 |
2374 24 | 25
2375 26 |
2376 28 |
2377 30 | 31
2378 32 |
2379 34 |
2380 36 | 37
2381 38 |
2382 40 |
2383(10 rows)
2384
2385ALTER VIEW v4 OWNER TO regress_view_owner;
2386EXPLAIN (VERBOSE, COSTS OFF)
2387SELECT 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
2388                                                                                QUERY PLAN
2389--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2390 Limit
2391   Output: ft4.c1, ft5.c2, ft5.c1
2392   ->  Foreign Scan
2393         Output: ft4.c1, ft5.c2, ft5.c1
2394         Relations: (public.ft4) LEFT JOIN (public.ft5)
2395         Remote SQL: SELECT r6.c1, r9.c2, r9.c1 FROM ("S 1"."T 3" r6 LEFT JOIN "S 1"."T 4" r9 ON (((r6.c1 = r9.c1)))) ORDER BY r6.c1 ASC NULLS LAST, r9.c1 ASC NULLS LAST
2396(6 rows)
2397
2398SELECT 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;
2399 c1 | c2
2400----+----
2401 22 |
2402 24 | 25
2403 26 |
2404 28 |
2405 30 | 31
2406 32 |
2407 34 |
2408 36 | 37
2409 38 |
2410 40 |
2411(10 rows)
2412
2413EXPLAIN (VERBOSE, COSTS OFF)
2414SELECT 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
2415                              QUERY PLAN
2416----------------------------------------------------------------------
2417 Limit
2418   Output: ft4.c1, t2.c2, t2.c1
2419   ->  Sort
2420         Output: ft4.c1, t2.c2, t2.c1
2421         Sort Key: ft4.c1, t2.c1
2422         ->  Hash Left Join
2423               Output: ft4.c1, t2.c2, t2.c1
2424               Hash Cond: (ft4.c1 = t2.c1)
2425               ->  Foreign Scan on public.ft4
2426                     Output: ft4.c1, ft4.c2, ft4.c3
2427                     Remote SQL: SELECT c1 FROM "S 1"."T 3"
2428               ->  Hash
2429                     Output: t2.c2, t2.c1
2430                     ->  Foreign Scan on public.ft5 t2
2431                           Output: t2.c2, t2.c1
2432                           Remote SQL: SELECT c1, c2 FROM "S 1"."T 4"
2433(16 rows)
2434
2435SELECT 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;
2436 c1 | c2
2437----+----
2438 22 |
2439 24 | 25
2440 26 |
2441 28 |
2442 30 | 31
2443 32 |
2444 34 |
2445 36 | 37
2446 38 |
2447 40 |
2448(10 rows)
2449
2450ALTER VIEW v4 OWNER TO CURRENT_USER;
2451EXPLAIN (VERBOSE, COSTS OFF)
2452SELECT 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
2453                                                                                QUERY PLAN
2454--------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2455 Limit
2456   Output: ft4.c1, t2.c2, t2.c1
2457   ->  Foreign Scan
2458         Output: ft4.c1, t2.c2, t2.c1
2459         Relations: (public.ft4) LEFT JOIN (public.ft5 t2)
2460         Remote SQL: SELECT r6.c1, r2.c2, r2.c1 FROM ("S 1"."T 3" r6 LEFT JOIN "S 1"."T 4" r2 ON (((r6.c1 = r2.c1)))) ORDER BY r6.c1 ASC NULLS LAST, r2.c1 ASC NULLS LAST
2461(6 rows)
2462
2463SELECT 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;
2464 c1 | c2
2465----+----
2466 22 |
2467 24 | 25
2468 26 |
2469 28 |
2470 30 | 31
2471 32 |
2472 34 |
2473 36 | 37
2474 38 |
2475 40 |
2476(10 rows)
2477
2478ALTER VIEW v4 OWNER TO regress_view_owner;
2479-- cleanup
2480DROP OWNED BY regress_view_owner;
2481DROP ROLE regress_view_owner;
2482-- ===================================================================
2483-- parameterized queries
2484-- ===================================================================
2485-- simple join
2486PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $1 AND t2.c1 = $2;
2487EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2);
2488                                                          QUERY PLAN
2489------------------------------------------------------------------------------------------------------------------------------
2490 Foreign Scan
2491   Output: t1.c3, t2.c3
2492   Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2493   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))))
2494(4 rows)
2495
2496EXECUTE st1(1, 1);
2497  c3   |  c3
2498-------+-------
2499 00001 | 00001
2500(1 row)
2501
2502EXECUTE st1(101, 101);
2503  c3   |  c3
2504-------+-------
2505 00101 | 00101
2506(1 row)
2507
2508-- subquery using stable function (can't be sent to remote)
2509PREPARE 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;
2510EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st2(10, 20);
2511                                                QUERY PLAN
2512----------------------------------------------------------------------------------------------------------
2513 Sort
2514   Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
2515   Sort Key: t1.c1
2516   ->  Nested Loop Semi Join
2517         Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
2518         Join Filter: (t1.c3 = t2.c3)
2519         ->  Foreign Scan on public.ft1 t1
2520               Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
2521               Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 20))
2522         ->  Materialize
2523               Output: t2.c3
2524               ->  Foreign Scan on public.ft2 t2
2525                     Output: t2.c3
2526                     Filter: (date(t2.c4) = '01-17-1970'::date)
2527                     Remote SQL: SELECT c3, c4 FROM "S 1"."T 1" WHERE (("C 1" > 10))
2528(15 rows)
2529
2530EXECUTE st2(10, 20);
2531 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2532----+----+-------+------------------------------+--------------------------+----+------------+-----
2533 16 |  6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
2534(1 row)
2535
2536EXECUTE st2(101, 121);
2537 c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2538-----+----+-------+------------------------------+--------------------------+----+------------+-----
2539 116 |  6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
2540(1 row)
2541
2542-- subquery using immutable function (can be sent to remote)
2543PREPARE 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;
2544EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st3(10, 20);
2545                                                      QUERY PLAN
2546-----------------------------------------------------------------------------------------------------------------------
2547 Sort
2548   Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
2549   Sort Key: t1.c1
2550   ->  Nested Loop Semi Join
2551         Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
2552         Join Filter: (t1.c3 = t2.c3)
2553         ->  Foreign Scan on public.ft1 t1
2554               Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
2555               Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 20))
2556         ->  Materialize
2557               Output: t2.c3
2558               ->  Foreign Scan on public.ft2 t2
2559                     Output: t2.c3
2560                     Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" > 10)) AND ((date(c5) = '1970-01-17'::date))
2561(14 rows)
2562
2563EXECUTE st3(10, 20);
2564 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2565----+----+-------+------------------------------+--------------------------+----+------------+-----
2566 16 |  6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
2567(1 row)
2568
2569EXECUTE st3(20, 30);
2570 c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8
2571----+----+----+----+----+----+----+----
2572(0 rows)
2573
2574-- custom plan should be chosen initially
2575PREPARE st4(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 = $1;
2576EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
2577                                         QUERY PLAN
2578---------------------------------------------------------------------------------------------
2579 Foreign Scan on public.ft1 t1
2580   Output: c1, c2, c3, c4, c5, c6, c7, c8
2581   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
2582(3 rows)
2583
2584EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
2585                                         QUERY PLAN
2586---------------------------------------------------------------------------------------------
2587 Foreign Scan on public.ft1 t1
2588   Output: c1, c2, c3, c4, c5, c6, c7, c8
2589   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
2590(3 rows)
2591
2592EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
2593                                         QUERY PLAN
2594---------------------------------------------------------------------------------------------
2595 Foreign Scan on public.ft1 t1
2596   Output: c1, c2, c3, c4, c5, c6, c7, c8
2597   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
2598(3 rows)
2599
2600EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
2601                                         QUERY PLAN
2602---------------------------------------------------------------------------------------------
2603 Foreign Scan on public.ft1 t1
2604   Output: c1, c2, c3, c4, c5, c6, c7, c8
2605   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
2606(3 rows)
2607
2608EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
2609                                         QUERY PLAN
2610---------------------------------------------------------------------------------------------
2611 Foreign Scan on public.ft1 t1
2612   Output: c1, c2, c3, c4, c5, c6, c7, c8
2613   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
2614(3 rows)
2615
2616-- once we try it enough times, should switch to generic plan
2617EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
2618                                              QUERY PLAN
2619-------------------------------------------------------------------------------------------------------
2620 Foreign Scan on public.ft1 t1
2621   Output: c1, c2, c3, c4, c5, c6, c7, c8
2622   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
2623(3 rows)
2624
2625-- value of $1 should not be sent to remote
2626PREPARE st5(user_enum,int) AS SELECT * FROM ft1 t1 WHERE c8 = $1 and c1 = $2;
2627EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
2628                                         QUERY PLAN
2629---------------------------------------------------------------------------------------------
2630 Foreign Scan on public.ft1 t1
2631   Output: c1, c2, c3, c4, c5, c6, c7, c8
2632   Filter: (t1.c8 = 'foo'::user_enum)
2633   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
2634(4 rows)
2635
2636EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
2637                                         QUERY PLAN
2638---------------------------------------------------------------------------------------------
2639 Foreign Scan on public.ft1 t1
2640   Output: c1, c2, c3, c4, c5, c6, c7, c8
2641   Filter: (t1.c8 = 'foo'::user_enum)
2642   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
2643(4 rows)
2644
2645EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
2646                                         QUERY PLAN
2647---------------------------------------------------------------------------------------------
2648 Foreign Scan on public.ft1 t1
2649   Output: c1, c2, c3, c4, c5, c6, c7, c8
2650   Filter: (t1.c8 = 'foo'::user_enum)
2651   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
2652(4 rows)
2653
2654EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
2655                                         QUERY PLAN
2656---------------------------------------------------------------------------------------------
2657 Foreign Scan on public.ft1 t1
2658   Output: c1, c2, c3, c4, c5, c6, c7, c8
2659   Filter: (t1.c8 = 'foo'::user_enum)
2660   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
2661(4 rows)
2662
2663EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
2664                                         QUERY PLAN
2665---------------------------------------------------------------------------------------------
2666 Foreign Scan on public.ft1 t1
2667   Output: c1, c2, c3, c4, c5, c6, c7, c8
2668   Filter: (t1.c8 = 'foo'::user_enum)
2669   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
2670(4 rows)
2671
2672EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
2673                                              QUERY PLAN
2674-------------------------------------------------------------------------------------------------------
2675 Foreign Scan on public.ft1 t1
2676   Output: c1, c2, c3, c4, c5, c6, c7, c8
2677   Filter: (t1.c8 = $1)
2678   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
2679(4 rows)
2680
2681EXECUTE st5('foo', 1);
2682 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2683----+----+-------+------------------------------+--------------------------+----+------------+-----
2684  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
2685(1 row)
2686
2687-- altering FDW options requires replanning
2688PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2;
2689EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
2690                                          QUERY PLAN
2691----------------------------------------------------------------------------------------------
2692 Foreign Scan on public.ft1 t1
2693   Output: c1, c2, c3, c4, c5, c6, c7, c8
2694   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = c2))
2695(3 rows)
2696
2697PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo');
2698EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
2699                                                                                           QUERY PLAN
2700-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2701 Insert on public.ft1
2702   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)
2703   ->  Result
2704         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
2705(4 rows)
2706
2707ALTER TABLE "S 1"."T 1" RENAME TO "T 0";
2708ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 0');
2709EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
2710                                          QUERY PLAN
2711----------------------------------------------------------------------------------------------
2712 Foreign Scan on public.ft1 t1
2713   Output: c1, c2, c3, c4, c5, c6, c7, c8
2714   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 0" WHERE (("C 1" = c2))
2715(3 rows)
2716
2717EXECUTE st6;
2718 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2719----+----+-------+------------------------------+--------------------------+----+------------+-----
2720  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
2721  2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
2722  3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
2723  4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
2724  5 |  5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
2725  6 |  6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
2726  7 |  7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
2727  8 |  8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
2728  9 |  9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
2729(9 rows)
2730
2731EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
2732                                                                                           QUERY PLAN
2733-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2734 Insert on public.ft1
2735   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)
2736   ->  Result
2737         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
2738(4 rows)
2739
2740ALTER TABLE "S 1"."T 0" RENAME TO "T 1";
2741ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 1');
2742PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
2743EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
2744                                       QUERY PLAN
2745----------------------------------------------------------------------------------------
2746 Aggregate
2747   Output: count(c3)
2748   ->  Foreign Scan on public.ft1 t1
2749         Output: c3
2750         Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2))
2751(5 rows)
2752
2753ALTER SERVER loopback OPTIONS (DROP extensions);
2754EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
2755                        QUERY PLAN
2756-----------------------------------------------------------
2757 Aggregate
2758   Output: count(c3)
2759   ->  Foreign Scan on public.ft1 t1
2760         Output: c3
2761         Filter: (t1.c1 === t1.c2)
2762         Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
2763(6 rows)
2764
2765EXECUTE st8;
2766 count
2767-------
2768     9
2769(1 row)
2770
2771ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
2772-- cleanup
2773DEALLOCATE st1;
2774DEALLOCATE st2;
2775DEALLOCATE st3;
2776DEALLOCATE st4;
2777DEALLOCATE st5;
2778DEALLOCATE st6;
2779DEALLOCATE st7;
2780DEALLOCATE st8;
2781-- System columns, except ctid, should not be sent to remote
2782EXPLAIN (VERBOSE, COSTS OFF)
2783SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
2784                                  QUERY PLAN
2785-------------------------------------------------------------------------------
2786 Limit
2787   Output: c1, c2, c3, c4, c5, c6, c7, c8
2788   ->  Foreign Scan on public.ft1 t1
2789         Output: c1, c2, c3, c4, c5, c6, c7, c8
2790         Filter: (t1.tableoid = '1259'::oid)
2791         Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
2792(6 rows)
2793
2794SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1;
2795 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2796----+----+-------+------------------------------+--------------------------+----+------------+-----
2797  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
2798(1 row)
2799
2800EXPLAIN (VERBOSE, COSTS OFF)
2801SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1;
2802                                  QUERY PLAN
2803-------------------------------------------------------------------------------
2804 Limit
2805   Output: ((tableoid)::regclass), c1, c2, c3, c4, c5, c6, c7, c8
2806   ->  Foreign Scan on public.ft1 t1
2807         Output: (tableoid)::regclass, c1, c2, c3, c4, c5, c6, c7, c8
2808         Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
2809(5 rows)
2810
2811SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1;
2812 tableoid | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2813----------+----+----+-------+------------------------------+--------------------------+----+------------+-----
2814 ft1      |  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
2815(1 row)
2816
2817EXPLAIN (VERBOSE, COSTS OFF)
2818SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)';
2819                                              QUERY PLAN
2820-------------------------------------------------------------------------------------------------------
2821 Foreign Scan on public.ft1 t1
2822   Output: c1, c2, c3, c4, c5, c6, c7, c8
2823   Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((ctid = '(0,2)'::tid))
2824(3 rows)
2825
2826SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)';
2827 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2828----+----+-------+------------------------------+--------------------------+----+------------+-----
2829  2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
2830(1 row)
2831
2832EXPLAIN (VERBOSE, COSTS OFF)
2833SELECT ctid, * FROM ft1 t1 LIMIT 1;
2834                                     QUERY PLAN
2835-------------------------------------------------------------------------------------
2836 Limit
2837   Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8
2838   ->  Foreign Scan on public.ft1 t1
2839         Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8
2840         Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1"
2841(5 rows)
2842
2843SELECT ctid, * FROM ft1 t1 LIMIT 1;
2844 ctid  | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2845-------+----+----+-------+------------------------------+--------------------------+----+------------+-----
2846 (0,1) |  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
2847(1 row)
2848
2849-- ===================================================================
2850-- used in pl/pgsql function
2851-- ===================================================================
2852CREATE OR REPLACE FUNCTION f_test(p_c1 int) RETURNS int AS $$
2853DECLARE
2854	v_c1 int;
2855BEGIN
2856    SELECT c1 INTO v_c1 FROM ft1 WHERE c1 = p_c1 LIMIT 1;
2857    PERFORM c1 FROM ft1 WHERE c1 = p_c1 AND p_c1 = v_c1 LIMIT 1;
2858    RETURN v_c1;
2859END;
2860$$ LANGUAGE plpgsql;
2861SELECT f_test(100);
2862 f_test
2863--------
2864    100
2865(1 row)
2866
2867DROP FUNCTION f_test(int);
2868-- ===================================================================
2869-- conversion error
2870-- ===================================================================
2871ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int;
2872SELECT * FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8) WHERE x1 = 1;  -- ERROR
2873ERROR:  invalid input syntax for integer: "foo"
2874CONTEXT:  column "x8" of foreign table "ftx"
2875SELECT ftx.x1, ft2.c2, ftx.x8 FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8), ft2
2876  WHERE ftx.x1 = ft2.c1 AND ftx.x1 = 1; -- ERROR
2877ERROR:  invalid input syntax for integer: "foo"
2878CONTEXT:  column "x8" of foreign table "ftx"
2879SELECT ftx.x1, ft2.c2, ftx FROM ft1 ftx(x1,x2,x3,x4,x5,x6,x7,x8), ft2
2880  WHERE ftx.x1 = ft2.c1 AND ftx.x1 = 1; -- ERROR
2881ERROR:  invalid input syntax for integer: "foo"
2882CONTEXT:  whole-row reference to foreign table "ftx"
2883ANALYZE ft1; -- ERROR
2884ERROR:  invalid input syntax for integer: "foo"
2885CONTEXT:  column "c8" of foreign table "ft1"
2886ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum;
2887-- ===================================================================
2888-- subtransaction
2889--  + local/remote error doesn't break cursor
2890-- ===================================================================
2891BEGIN;
2892DECLARE c CURSOR FOR SELECT * FROM ft1 ORDER BY c1;
2893FETCH c;
2894 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2895----+----+-------+------------------------------+--------------------------+----+------------+-----
2896  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
2897(1 row)
2898
2899SAVEPOINT s;
2900ERROR OUT;          -- ERROR
2901ERROR:  syntax error at or near "ERROR"
2902LINE 1: ERROR OUT;
2903        ^
2904ROLLBACK TO s;
2905FETCH c;
2906 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2907----+----+-------+------------------------------+--------------------------+----+------------+-----
2908  2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
2909(1 row)
2910
2911SAVEPOINT s;
2912SELECT * FROM ft1 WHERE 1 / (c1 - 1) > 0;  -- ERROR
2913ERROR:  division by zero
2914CONTEXT:  Remote SQL command: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (((1 / ("C 1" - 1)) > 0))
2915ROLLBACK TO s;
2916FETCH c;
2917 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2918----+----+-------+------------------------------+--------------------------+----+------------+-----
2919  3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
2920(1 row)
2921
2922SELECT * FROM ft1 ORDER BY c1 LIMIT 1;
2923 c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8
2924----+----+-------+------------------------------+--------------------------+----+------------+-----
2925  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
2926(1 row)
2927
2928COMMIT;
2929-- ===================================================================
2930-- test handling of collations
2931-- ===================================================================
2932create table loct3 (f1 text collate "C" unique, f2 text, f3 varchar(10) unique);
2933create foreign table ft3 (f1 text collate "C", f2 text, f3 varchar(10))
2934  server loopback options (table_name 'loct3', use_remote_estimate 'true');
2935-- can be sent to remote
2936explain (verbose, costs off) select * from ft3 where f1 = 'foo';
2937                                  QUERY PLAN
2938------------------------------------------------------------------------------
2939 Foreign Scan on public.ft3
2940   Output: f1, f2, f3
2941   Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f1 = 'foo'::text))
2942(3 rows)
2943
2944explain (verbose, costs off) select * from ft3 where f1 COLLATE "C" = 'foo';
2945                                  QUERY PLAN
2946------------------------------------------------------------------------------
2947 Foreign Scan on public.ft3
2948   Output: f1, f2, f3
2949   Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f1 = 'foo'::text))
2950(3 rows)
2951
2952explain (verbose, costs off) select * from ft3 where f2 = 'foo';
2953                                  QUERY PLAN
2954------------------------------------------------------------------------------
2955 Foreign Scan on public.ft3
2956   Output: f1, f2, f3
2957   Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f2 = 'foo'::text))
2958(3 rows)
2959
2960explain (verbose, costs off) select * from ft3 where f3 = 'foo';
2961                                  QUERY PLAN
2962------------------------------------------------------------------------------
2963 Foreign Scan on public.ft3
2964   Output: f1, f2, f3
2965   Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f3 = 'foo'::text))
2966(3 rows)
2967
2968explain (verbose, costs off) select * from ft3 f, loct3 l
2969  where f.f3 = l.f3 and l.f1 = 'foo';
2970                                            QUERY PLAN
2971--------------------------------------------------------------------------------------------------
2972 Nested Loop
2973   Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
2974   ->  Index Scan using loct3_f1_key on public.loct3 l
2975         Output: l.f1, l.f2, l.f3
2976         Index Cond: (l.f1 = 'foo'::text)
2977   ->  Foreign Scan on public.ft3 f
2978         Output: f.f1, f.f2, f.f3
2979         Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE (($1::character varying(10) = f3))
2980(8 rows)
2981
2982-- can't be sent to remote
2983explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo';
2984                    QUERY PLAN
2985---------------------------------------------------
2986 Foreign Scan on public.ft3
2987   Output: f1, f2, f3
2988   Filter: ((ft3.f1)::text = 'foo'::text)
2989   Remote SQL: SELECT f1, f2, f3 FROM public.loct3
2990(4 rows)
2991
2992explain (verbose, costs off) select * from ft3 where f1 = 'foo' COLLATE "C";
2993                    QUERY PLAN
2994---------------------------------------------------
2995 Foreign Scan on public.ft3
2996   Output: f1, f2, f3
2997   Filter: (ft3.f1 = 'foo'::text COLLATE "C")
2998   Remote SQL: SELECT f1, f2, f3 FROM public.loct3
2999(4 rows)
3000
3001explain (verbose, costs off) select * from ft3 where f2 COLLATE "C" = 'foo';
3002                    QUERY PLAN
3003---------------------------------------------------
3004 Foreign Scan on public.ft3
3005   Output: f1, f2, f3
3006   Filter: ((ft3.f2)::text = 'foo'::text)
3007   Remote SQL: SELECT f1, f2, f3 FROM public.loct3
3008(4 rows)
3009
3010explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C";
3011                    QUERY PLAN
3012---------------------------------------------------
3013 Foreign Scan on public.ft3
3014   Output: f1, f2, f3
3015   Filter: (ft3.f2 = 'foo'::text COLLATE "C")
3016   Remote SQL: SELECT f1, f2, f3 FROM public.loct3
3017(4 rows)
3018
3019explain (verbose, costs off) select * from ft3 f, loct3 l
3020  where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo';
3021                         QUERY PLAN
3022-------------------------------------------------------------
3023 Hash Join
3024   Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
3025   Hash Cond: ((f.f3)::text = (l.f3)::text)
3026   ->  Foreign Scan on public.ft3 f
3027         Output: f.f1, f.f2, f.f3
3028         Remote SQL: SELECT f1, f2, f3 FROM public.loct3
3029   ->  Hash
3030         Output: l.f1, l.f2, l.f3
3031         ->  Index Scan using loct3_f1_key on public.loct3 l
3032               Output: l.f1, l.f2, l.f3
3033               Index Cond: (l.f1 = 'foo'::text)
3034(11 rows)
3035
3036-- ===================================================================
3037-- test writable foreign table stuff
3038-- ===================================================================
3039EXPLAIN (verbose, costs off)
3040INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
3041                                                                                                                    QUERY PLAN
3042--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3043 Insert on public.ft2
3044   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)
3045   ->  Subquery Scan on "*SELECT*"
3046         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
3047         ->  Limit
3048               Output: ((ft2_1.c1 + 1000)), ((ft2_1.c2 + 100)), ((ft2_1.c3 || ft2_1.c3))
3049               ->  Foreign Scan on public.ft2 ft2_1
3050                     Output: (ft2_1.c1 + 1000), (ft2_1.c2 + 100), (ft2_1.c3 || ft2_1.c3)
3051                     Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
3052(9 rows)
3053
3054INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
3055INSERT INTO ft2 (c1,c2,c3)
3056  VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING *;
3057  c1  | c2  | c3  | c4 | c5 | c6 |     c7     | c8
3058------+-----+-----+----+----+----+------------+----
3059 1101 | 201 | aaa |    |    |    | ft2        |
3060 1102 | 202 | bbb |    |    |    | ft2        |
3061 1103 | 203 | ccc |    |    |    | ft2        |
3062(3 rows)
3063
3064INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee');
3065EXPLAIN (verbose, costs off)
3066UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3;              -- can be pushed down
3067                                                      QUERY PLAN
3068----------------------------------------------------------------------------------------------------------------------
3069 Update on public.ft2
3070   ->  Foreign Update on public.ft2
3071         Remote SQL: UPDATE "S 1"."T 1" SET c2 = (c2 + 300), c3 = (c3 || '_update3'::text) WHERE ((("C 1" % 10) = 3))
3072(3 rows)
3073
3074UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3;
3075EXPLAIN (verbose, costs off)
3076UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *;  -- can be pushed down
3077                                                                            QUERY PLAN
3078------------------------------------------------------------------------------------------------------------------------------------------------------------------
3079 Update on public.ft2
3080   Output: c1, c2, c3, c4, c5, c6, c7, c8
3081   ->  Foreign Update on public.ft2
3082         Remote SQL: UPDATE "S 1"."T 1" SET c2 = (c2 + 400), c3 = (c3 || '_update7'::text) WHERE ((("C 1" % 10) = 7)) RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8
3083(4 rows)
3084
3085UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *;
3086  c1  | c2  |         c3         |              c4              |            c5            | c6 |     c7     | c8
3087------+-----+--------------------+------------------------------+--------------------------+----+------------+-----
3088    7 | 407 | 00007_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3089   17 | 407 | 00017_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
3090   27 | 407 | 00027_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
3091   37 | 407 | 00037_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
3092   47 | 407 | 00047_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
3093   57 | 407 | 00057_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
3094   67 | 407 | 00067_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
3095   77 | 407 | 00077_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
3096   87 | 407 | 00087_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
3097   97 | 407 | 00097_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
3098  107 | 407 | 00107_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3099  117 | 407 | 00117_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
3100  127 | 407 | 00127_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
3101  137 | 407 | 00137_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
3102  147 | 407 | 00147_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
3103  157 | 407 | 00157_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
3104  167 | 407 | 00167_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
3105  177 | 407 | 00177_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
3106  187 | 407 | 00187_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
3107  197 | 407 | 00197_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
3108  207 | 407 | 00207_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3109  217 | 407 | 00217_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
3110  227 | 407 | 00227_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
3111  237 | 407 | 00237_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
3112  247 | 407 | 00247_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
3113  257 | 407 | 00257_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
3114  267 | 407 | 00267_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
3115  277 | 407 | 00277_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
3116  287 | 407 | 00287_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
3117  297 | 407 | 00297_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
3118  307 | 407 | 00307_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3119  317 | 407 | 00317_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
3120  327 | 407 | 00327_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
3121  337 | 407 | 00337_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
3122  347 | 407 | 00347_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
3123  357 | 407 | 00357_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
3124  367 | 407 | 00367_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
3125  377 | 407 | 00377_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
3126  387 | 407 | 00387_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
3127  397 | 407 | 00397_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
3128  407 | 407 | 00407_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3129  417 | 407 | 00417_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
3130  427 | 407 | 00427_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
3131  437 | 407 | 00437_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
3132  447 | 407 | 00447_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
3133  457 | 407 | 00457_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
3134  467 | 407 | 00467_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
3135  477 | 407 | 00477_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
3136  487 | 407 | 00487_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
3137  497 | 407 | 00497_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
3138  507 | 407 | 00507_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3139  517 | 407 | 00517_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
3140  527 | 407 | 00527_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
3141  537 | 407 | 00537_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
3142  547 | 407 | 00547_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
3143  557 | 407 | 00557_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
3144  567 | 407 | 00567_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
3145  577 | 407 | 00577_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
3146  587 | 407 | 00587_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
3147  597 | 407 | 00597_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
3148  607 | 407 | 00607_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3149  617 | 407 | 00617_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
3150  627 | 407 | 00627_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
3151  637 | 407 | 00637_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
3152  647 | 407 | 00647_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
3153  657 | 407 | 00657_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
3154  667 | 407 | 00667_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
3155  677 | 407 | 00677_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
3156  687 | 407 | 00687_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
3157  697 | 407 | 00697_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
3158  707 | 407 | 00707_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3159  717 | 407 | 00717_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
3160  727 | 407 | 00727_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
3161  737 | 407 | 00737_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
3162  747 | 407 | 00747_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
3163  757 | 407 | 00757_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
3164  767 | 407 | 00767_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
3165  777 | 407 | 00777_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
3166  787 | 407 | 00787_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
3167  797 | 407 | 00797_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
3168  807 | 407 | 00807_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3169  817 | 407 | 00817_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
3170  827 | 407 | 00827_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
3171  837 | 407 | 00837_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
3172  847 | 407 | 00847_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
3173  857 | 407 | 00857_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
3174  867 | 407 | 00867_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
3175  877 | 407 | 00877_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
3176  887 | 407 | 00887_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
3177  897 | 407 | 00897_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
3178  907 | 407 | 00907_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3179  917 | 407 | 00917_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
3180  927 | 407 | 00927_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
3181  937 | 407 | 00937_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
3182  947 | 407 | 00947_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
3183  957 | 407 | 00957_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
3184  967 | 407 | 00967_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
3185  977 | 407 | 00977_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
3186  987 | 407 | 00987_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
3187  997 | 407 | 00997_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
3188 1007 | 507 | 0000700007_update7 |                              |                          |    | ft2        |
3189 1017 | 507 | 0001700017_update7 |                              |                          |    | ft2        |
3190(102 rows)
3191
3192EXPLAIN (verbose, costs off)
3193UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
3194  FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9;                               -- can't be pushed down
3195                                                                                                                                                        QUERY PLAN
3196---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3197 Update on public.ft2
3198   Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c3 = $3, c7 = $4 WHERE ctid = $1
3199   ->  Foreign Scan
3200         Output: ft2.c1, (ft2.c2 + 500), NULL::integer, (ft2.c3 || '_update9'::text), ft2.c4, ft2.c5, ft2.c6, 'ft2       '::character(10), ft2.c8, ft2.ctid, ft1.*
3201         Relations: (public.ft2) INNER JOIN (public.ft1)
3202         Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c8, r1.ctid, 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.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 9)))) FOR UPDATE OF r1
3203         ->  Hash Join
3204               Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c8, ft2.ctid, ft1.*
3205               Hash Cond: (ft2.c2 = ft1.c1)
3206               ->  Foreign Scan on public.ft2
3207                     Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c8, ft2.ctid
3208                     Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c8, ctid FROM "S 1"."T 1" FOR UPDATE
3209               ->  Hash
3210                     Output: ft1.*, ft1.c1
3211                     ->  Foreign Scan on public.ft1
3212                           Output: ft1.*, ft1.c1
3213                           Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 9))
3214(17 rows)
3215
3216UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
3217  FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9;
3218EXPLAIN (verbose, costs off)
3219  DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4;                               -- can be pushed down
3220                                         QUERY PLAN
3221--------------------------------------------------------------------------------------------
3222 Delete on public.ft2
3223   Output: c1, c4
3224   ->  Foreign Delete on public.ft2
3225         Remote SQL: DELETE FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 5)) RETURNING "C 1", c4
3226(4 rows)
3227
3228DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4;
3229  c1  |              c4
3230------+------------------------------
3231    5 | Tue Jan 06 00:00:00 1970 PST
3232   15 | Fri Jan 16 00:00:00 1970 PST
3233   25 | Mon Jan 26 00:00:00 1970 PST
3234   35 | Thu Feb 05 00:00:00 1970 PST
3235   45 | Sun Feb 15 00:00:00 1970 PST
3236   55 | Wed Feb 25 00:00:00 1970 PST
3237   65 | Sat Mar 07 00:00:00 1970 PST
3238   75 | Tue Mar 17 00:00:00 1970 PST
3239   85 | Fri Mar 27 00:00:00 1970 PST
3240   95 | Mon Apr 06 00:00:00 1970 PST
3241  105 | Tue Jan 06 00:00:00 1970 PST
3242  115 | Fri Jan 16 00:00:00 1970 PST
3243  125 | Mon Jan 26 00:00:00 1970 PST
3244  135 | Thu Feb 05 00:00:00 1970 PST
3245  145 | Sun Feb 15 00:00:00 1970 PST
3246  155 | Wed Feb 25 00:00:00 1970 PST
3247  165 | Sat Mar 07 00:00:00 1970 PST
3248  175 | Tue Mar 17 00:00:00 1970 PST
3249  185 | Fri Mar 27 00:00:00 1970 PST
3250  195 | Mon Apr 06 00:00:00 1970 PST
3251  205 | Tue Jan 06 00:00:00 1970 PST
3252  215 | Fri Jan 16 00:00:00 1970 PST
3253  225 | Mon Jan 26 00:00:00 1970 PST
3254  235 | Thu Feb 05 00:00:00 1970 PST
3255  245 | Sun Feb 15 00:00:00 1970 PST
3256  255 | Wed Feb 25 00:00:00 1970 PST
3257  265 | Sat Mar 07 00:00:00 1970 PST
3258  275 | Tue Mar 17 00:00:00 1970 PST
3259  285 | Fri Mar 27 00:00:00 1970 PST
3260  295 | Mon Apr 06 00:00:00 1970 PST
3261  305 | Tue Jan 06 00:00:00 1970 PST
3262  315 | Fri Jan 16 00:00:00 1970 PST
3263  325 | Mon Jan 26 00:00:00 1970 PST
3264  335 | Thu Feb 05 00:00:00 1970 PST
3265  345 | Sun Feb 15 00:00:00 1970 PST
3266  355 | Wed Feb 25 00:00:00 1970 PST
3267  365 | Sat Mar 07 00:00:00 1970 PST
3268  375 | Tue Mar 17 00:00:00 1970 PST
3269  385 | Fri Mar 27 00:00:00 1970 PST
3270  395 | Mon Apr 06 00:00:00 1970 PST
3271  405 | Tue Jan 06 00:00:00 1970 PST
3272  415 | Fri Jan 16 00:00:00 1970 PST
3273  425 | Mon Jan 26 00:00:00 1970 PST
3274  435 | Thu Feb 05 00:00:00 1970 PST
3275  445 | Sun Feb 15 00:00:00 1970 PST
3276  455 | Wed Feb 25 00:00:00 1970 PST
3277  465 | Sat Mar 07 00:00:00 1970 PST
3278  475 | Tue Mar 17 00:00:00 1970 PST
3279  485 | Fri Mar 27 00:00:00 1970 PST
3280  495 | Mon Apr 06 00:00:00 1970 PST
3281  505 | Tue Jan 06 00:00:00 1970 PST
3282  515 | Fri Jan 16 00:00:00 1970 PST
3283  525 | Mon Jan 26 00:00:00 1970 PST
3284  535 | Thu Feb 05 00:00:00 1970 PST
3285  545 | Sun Feb 15 00:00:00 1970 PST
3286  555 | Wed Feb 25 00:00:00 1970 PST
3287  565 | Sat Mar 07 00:00:00 1970 PST
3288  575 | Tue Mar 17 00:00:00 1970 PST
3289  585 | Fri Mar 27 00:00:00 1970 PST
3290  595 | Mon Apr 06 00:00:00 1970 PST
3291  605 | Tue Jan 06 00:00:00 1970 PST
3292  615 | Fri Jan 16 00:00:00 1970 PST
3293  625 | Mon Jan 26 00:00:00 1970 PST
3294  635 | Thu Feb 05 00:00:00 1970 PST
3295  645 | Sun Feb 15 00:00:00 1970 PST
3296  655 | Wed Feb 25 00:00:00 1970 PST
3297  665 | Sat Mar 07 00:00:00 1970 PST
3298  675 | Tue Mar 17 00:00:00 1970 PST
3299  685 | Fri Mar 27 00:00:00 1970 PST
3300  695 | Mon Apr 06 00:00:00 1970 PST
3301  705 | Tue Jan 06 00:00:00 1970 PST
3302  715 | Fri Jan 16 00:00:00 1970 PST
3303  725 | Mon Jan 26 00:00:00 1970 PST
3304  735 | Thu Feb 05 00:00:00 1970 PST
3305  745 | Sun Feb 15 00:00:00 1970 PST
3306  755 | Wed Feb 25 00:00:00 1970 PST
3307  765 | Sat Mar 07 00:00:00 1970 PST
3308  775 | Tue Mar 17 00:00:00 1970 PST
3309  785 | Fri Mar 27 00:00:00 1970 PST
3310  795 | Mon Apr 06 00:00:00 1970 PST
3311  805 | Tue Jan 06 00:00:00 1970 PST
3312  815 | Fri Jan 16 00:00:00 1970 PST
3313  825 | Mon Jan 26 00:00:00 1970 PST
3314  835 | Thu Feb 05 00:00:00 1970 PST
3315  845 | Sun Feb 15 00:00:00 1970 PST
3316  855 | Wed Feb 25 00:00:00 1970 PST
3317  865 | Sat Mar 07 00:00:00 1970 PST
3318  875 | Tue Mar 17 00:00:00 1970 PST
3319  885 | Fri Mar 27 00:00:00 1970 PST
3320  895 | Mon Apr 06 00:00:00 1970 PST
3321  905 | Tue Jan 06 00:00:00 1970 PST
3322  915 | Fri Jan 16 00:00:00 1970 PST
3323  925 | Mon Jan 26 00:00:00 1970 PST
3324  935 | Thu Feb 05 00:00:00 1970 PST
3325  945 | Sun Feb 15 00:00:00 1970 PST
3326  955 | Wed Feb 25 00:00:00 1970 PST
3327  965 | Sat Mar 07 00:00:00 1970 PST
3328  975 | Tue Mar 17 00:00:00 1970 PST
3329  985 | Fri Mar 27 00:00:00 1970 PST
3330  995 | Mon Apr 06 00:00:00 1970 PST
3331 1005 |
3332 1015 |
3333 1105 |
3334(103 rows)
3335
3336EXPLAIN (verbose, costs off)
3337DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;                -- can't be pushed down
3338                                                                                                                              QUERY PLAN
3339-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3340 Delete on public.ft2
3341   Remote SQL: DELETE FROM "S 1"."T 1" WHERE ctid = $1
3342   ->  Foreign Scan
3343         Output: ft2.ctid, ft1.*
3344         Relations: (public.ft2) INNER JOIN (public.ft1)
3345         Remote SQL: SELECT r1.ctid, 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.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 2)))) FOR UPDATE OF r1
3346         ->  Hash Join
3347               Output: ft2.ctid, ft1.*
3348               Hash Cond: (ft2.c2 = ft1.c1)
3349               ->  Foreign Scan on public.ft2
3350                     Output: ft2.ctid, ft2.c2
3351                     Remote SQL: SELECT c2, ctid FROM "S 1"."T 1" FOR UPDATE
3352               ->  Hash
3353                     Output: ft1.*, ft1.c1
3354                     ->  Foreign Scan on public.ft1
3355                           Output: ft1.*, ft1.c1
3356                           Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 2))
3357(17 rows)
3358
3359DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;
3360SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1;
3361  c1  | c2  |         c3         |              c4
3362------+-----+--------------------+------------------------------
3363    1 |   1 | 00001              | Fri Jan 02 00:00:00 1970 PST
3364    3 | 303 | 00003_update3      | Sun Jan 04 00:00:00 1970 PST
3365    4 |   4 | 00004              | Mon Jan 05 00:00:00 1970 PST
3366    6 |   6 | 00006              | Wed Jan 07 00:00:00 1970 PST
3367    7 | 407 | 00007_update7      | Thu Jan 08 00:00:00 1970 PST
3368    8 |   8 | 00008              | Fri Jan 09 00:00:00 1970 PST
3369    9 | 509 | 00009_update9      | Sat Jan 10 00:00:00 1970 PST
3370   10 |   0 | 00010              | Sun Jan 11 00:00:00 1970 PST
3371   11 |   1 | 00011              | Mon Jan 12 00:00:00 1970 PST
3372   13 | 303 | 00013_update3      | Wed Jan 14 00:00:00 1970 PST
3373   14 |   4 | 00014              | Thu Jan 15 00:00:00 1970 PST
3374   16 |   6 | 00016              | Sat Jan 17 00:00:00 1970 PST
3375   17 | 407 | 00017_update7      | Sun Jan 18 00:00:00 1970 PST
3376   18 |   8 | 00018              | Mon Jan 19 00:00:00 1970 PST
3377   19 | 509 | 00019_update9      | Tue Jan 20 00:00:00 1970 PST
3378   20 |   0 | 00020              | Wed Jan 21 00:00:00 1970 PST
3379   21 |   1 | 00021              | Thu Jan 22 00:00:00 1970 PST
3380   23 | 303 | 00023_update3      | Sat Jan 24 00:00:00 1970 PST
3381   24 |   4 | 00024              | Sun Jan 25 00:00:00 1970 PST
3382   26 |   6 | 00026              | Tue Jan 27 00:00:00 1970 PST
3383   27 | 407 | 00027_update7      | Wed Jan 28 00:00:00 1970 PST
3384   28 |   8 | 00028              | Thu Jan 29 00:00:00 1970 PST
3385   29 | 509 | 00029_update9      | Fri Jan 30 00:00:00 1970 PST
3386   30 |   0 | 00030              | Sat Jan 31 00:00:00 1970 PST
3387   31 |   1 | 00031              | Sun Feb 01 00:00:00 1970 PST
3388   33 | 303 | 00033_update3      | Tue Feb 03 00:00:00 1970 PST
3389   34 |   4 | 00034              | Wed Feb 04 00:00:00 1970 PST
3390   36 |   6 | 00036              | Fri Feb 06 00:00:00 1970 PST
3391   37 | 407 | 00037_update7      | Sat Feb 07 00:00:00 1970 PST
3392   38 |   8 | 00038              | Sun Feb 08 00:00:00 1970 PST
3393   39 | 509 | 00039_update9      | Mon Feb 09 00:00:00 1970 PST
3394   40 |   0 | 00040              | Tue Feb 10 00:00:00 1970 PST
3395   41 |   1 | 00041              | Wed Feb 11 00:00:00 1970 PST
3396   43 | 303 | 00043_update3      | Fri Feb 13 00:00:00 1970 PST
3397   44 |   4 | 00044              | Sat Feb 14 00:00:00 1970 PST
3398   46 |   6 | 00046              | Mon Feb 16 00:00:00 1970 PST
3399   47 | 407 | 00047_update7      | Tue Feb 17 00:00:00 1970 PST
3400   48 |   8 | 00048              | Wed Feb 18 00:00:00 1970 PST
3401   49 | 509 | 00049_update9      | Thu Feb 19 00:00:00 1970 PST
3402   50 |   0 | 00050              | Fri Feb 20 00:00:00 1970 PST
3403   51 |   1 | 00051              | Sat Feb 21 00:00:00 1970 PST
3404   53 | 303 | 00053_update3      | Mon Feb 23 00:00:00 1970 PST
3405   54 |   4 | 00054              | Tue Feb 24 00:00:00 1970 PST
3406   56 |   6 | 00056              | Thu Feb 26 00:00:00 1970 PST
3407   57 | 407 | 00057_update7      | Fri Feb 27 00:00:00 1970 PST
3408   58 |   8 | 00058              | Sat Feb 28 00:00:00 1970 PST
3409   59 | 509 | 00059_update9      | Sun Mar 01 00:00:00 1970 PST
3410   60 |   0 | 00060              | Mon Mar 02 00:00:00 1970 PST
3411   61 |   1 | 00061              | Tue Mar 03 00:00:00 1970 PST
3412   63 | 303 | 00063_update3      | Thu Mar 05 00:00:00 1970 PST
3413   64 |   4 | 00064              | Fri Mar 06 00:00:00 1970 PST
3414   66 |   6 | 00066              | Sun Mar 08 00:00:00 1970 PST
3415   67 | 407 | 00067_update7      | Mon Mar 09 00:00:00 1970 PST
3416   68 |   8 | 00068              | Tue Mar 10 00:00:00 1970 PST
3417   69 | 509 | 00069_update9      | Wed Mar 11 00:00:00 1970 PST
3418   70 |   0 | 00070              | Thu Mar 12 00:00:00 1970 PST
3419   71 |   1 | 00071              | Fri Mar 13 00:00:00 1970 PST
3420   73 | 303 | 00073_update3      | Sun Mar 15 00:00:00 1970 PST
3421   74 |   4 | 00074              | Mon Mar 16 00:00:00 1970 PST
3422   76 |   6 | 00076              | Wed Mar 18 00:00:00 1970 PST
3423   77 | 407 | 00077_update7      | Thu Mar 19 00:00:00 1970 PST
3424   78 |   8 | 00078              | Fri Mar 20 00:00:00 1970 PST
3425   79 | 509 | 00079_update9      | Sat Mar 21 00:00:00 1970 PST
3426   80 |   0 | 00080              | Sun Mar 22 00:00:00 1970 PST
3427   81 |   1 | 00081              | Mon Mar 23 00:00:00 1970 PST
3428   83 | 303 | 00083_update3      | Wed Mar 25 00:00:00 1970 PST
3429   84 |   4 | 00084              | Thu Mar 26 00:00:00 1970 PST
3430   86 |   6 | 00086              | Sat Mar 28 00:00:00 1970 PST
3431   87 | 407 | 00087_update7      | Sun Mar 29 00:00:00 1970 PST
3432   88 |   8 | 00088              | Mon Mar 30 00:00:00 1970 PST
3433   89 | 509 | 00089_update9      | Tue Mar 31 00:00:00 1970 PST
3434   90 |   0 | 00090              | Wed Apr 01 00:00:00 1970 PST
3435   91 |   1 | 00091              | Thu Apr 02 00:00:00 1970 PST
3436   93 | 303 | 00093_update3      | Sat Apr 04 00:00:00 1970 PST
3437   94 |   4 | 00094              | Sun Apr 05 00:00:00 1970 PST
3438   96 |   6 | 00096              | Tue Apr 07 00:00:00 1970 PST
3439   97 | 407 | 00097_update7      | Wed Apr 08 00:00:00 1970 PST
3440   98 |   8 | 00098              | Thu Apr 09 00:00:00 1970 PST
3441   99 | 509 | 00099_update9      | Fri Apr 10 00:00:00 1970 PST
3442  100 |   0 | 00100              | Thu Jan 01 00:00:00 1970 PST
3443  101 |   1 | 00101              | Fri Jan 02 00:00:00 1970 PST
3444  103 | 303 | 00103_update3      | Sun Jan 04 00:00:00 1970 PST
3445  104 |   4 | 00104              | Mon Jan 05 00:00:00 1970 PST
3446  106 |   6 | 00106              | Wed Jan 07 00:00:00 1970 PST
3447  107 | 407 | 00107_update7      | Thu Jan 08 00:00:00 1970 PST
3448  108 |   8 | 00108              | Fri Jan 09 00:00:00 1970 PST
3449  109 | 509 | 00109_update9      | Sat Jan 10 00:00:00 1970 PST
3450  110 |   0 | 00110              | Sun Jan 11 00:00:00 1970 PST
3451  111 |   1 | 00111              | Mon Jan 12 00:00:00 1970 PST
3452  113 | 303 | 00113_update3      | Wed Jan 14 00:00:00 1970 PST
3453  114 |   4 | 00114              | Thu Jan 15 00:00:00 1970 PST
3454  116 |   6 | 00116              | Sat Jan 17 00:00:00 1970 PST
3455  117 | 407 | 00117_update7      | Sun Jan 18 00:00:00 1970 PST
3456  118 |   8 | 00118              | Mon Jan 19 00:00:00 1970 PST
3457  119 | 509 | 00119_update9      | Tue Jan 20 00:00:00 1970 PST
3458  120 |   0 | 00120              | Wed Jan 21 00:00:00 1970 PST
3459  121 |   1 | 00121              | Thu Jan 22 00:00:00 1970 PST
3460  123 | 303 | 00123_update3      | Sat Jan 24 00:00:00 1970 PST
3461  124 |   4 | 00124              | Sun Jan 25 00:00:00 1970 PST
3462  126 |   6 | 00126              | Tue Jan 27 00:00:00 1970 PST
3463  127 | 407 | 00127_update7      | Wed Jan 28 00:00:00 1970 PST
3464  128 |   8 | 00128              | Thu Jan 29 00:00:00 1970 PST
3465  129 | 509 | 00129_update9      | Fri Jan 30 00:00:00 1970 PST
3466  130 |   0 | 00130              | Sat Jan 31 00:00:00 1970 PST
3467  131 |   1 | 00131              | Sun Feb 01 00:00:00 1970 PST
3468  133 | 303 | 00133_update3      | Tue Feb 03 00:00:00 1970 PST
3469  134 |   4 | 00134              | Wed Feb 04 00:00:00 1970 PST
3470  136 |   6 | 00136              | Fri Feb 06 00:00:00 1970 PST
3471  137 | 407 | 00137_update7      | Sat Feb 07 00:00:00 1970 PST
3472  138 |   8 | 00138              | Sun Feb 08 00:00:00 1970 PST
3473  139 | 509 | 00139_update9      | Mon Feb 09 00:00:00 1970 PST
3474  140 |   0 | 00140              | Tue Feb 10 00:00:00 1970 PST
3475  141 |   1 | 00141              | Wed Feb 11 00:00:00 1970 PST
3476  143 | 303 | 00143_update3      | Fri Feb 13 00:00:00 1970 PST
3477  144 |   4 | 00144              | Sat Feb 14 00:00:00 1970 PST
3478  146 |   6 | 00146              | Mon Feb 16 00:00:00 1970 PST
3479  147 | 407 | 00147_update7      | Tue Feb 17 00:00:00 1970 PST
3480  148 |   8 | 00148              | Wed Feb 18 00:00:00 1970 PST
3481  149 | 509 | 00149_update9      | Thu Feb 19 00:00:00 1970 PST
3482  150 |   0 | 00150              | Fri Feb 20 00:00:00 1970 PST
3483  151 |   1 | 00151              | Sat Feb 21 00:00:00 1970 PST
3484  153 | 303 | 00153_update3      | Mon Feb 23 00:00:00 1970 PST
3485  154 |   4 | 00154              | Tue Feb 24 00:00:00 1970 PST
3486  156 |   6 | 00156              | Thu Feb 26 00:00:00 1970 PST
3487  157 | 407 | 00157_update7      | Fri Feb 27 00:00:00 1970 PST
3488  158 |   8 | 00158              | Sat Feb 28 00:00:00 1970 PST
3489  159 | 509 | 00159_update9      | Sun Mar 01 00:00:00 1970 PST
3490  160 |   0 | 00160              | Mon Mar 02 00:00:00 1970 PST
3491  161 |   1 | 00161              | Tue Mar 03 00:00:00 1970 PST
3492  163 | 303 | 00163_update3      | Thu Mar 05 00:00:00 1970 PST
3493  164 |   4 | 00164              | Fri Mar 06 00:00:00 1970 PST
3494  166 |   6 | 00166              | Sun Mar 08 00:00:00 1970 PST
3495  167 | 407 | 00167_update7      | Mon Mar 09 00:00:00 1970 PST
3496  168 |   8 | 00168              | Tue Mar 10 00:00:00 1970 PST
3497  169 | 509 | 00169_update9      | Wed Mar 11 00:00:00 1970 PST
3498  170 |   0 | 00170              | Thu Mar 12 00:00:00 1970 PST
3499  171 |   1 | 00171              | Fri Mar 13 00:00:00 1970 PST
3500  173 | 303 | 00173_update3      | Sun Mar 15 00:00:00 1970 PST
3501  174 |   4 | 00174              | Mon Mar 16 00:00:00 1970 PST
3502  176 |   6 | 00176              | Wed Mar 18 00:00:00 1970 PST
3503  177 | 407 | 00177_update7      | Thu Mar 19 00:00:00 1970 PST
3504  178 |   8 | 00178              | Fri Mar 20 00:00:00 1970 PST
3505  179 | 509 | 00179_update9      | Sat Mar 21 00:00:00 1970 PST
3506  180 |   0 | 00180              | Sun Mar 22 00:00:00 1970 PST
3507  181 |   1 | 00181              | Mon Mar 23 00:00:00 1970 PST
3508  183 | 303 | 00183_update3      | Wed Mar 25 00:00:00 1970 PST
3509  184 |   4 | 00184              | Thu Mar 26 00:00:00 1970 PST
3510  186 |   6 | 00186              | Sat Mar 28 00:00:00 1970 PST
3511  187 | 407 | 00187_update7      | Sun Mar 29 00:00:00 1970 PST
3512  188 |   8 | 00188              | Mon Mar 30 00:00:00 1970 PST
3513  189 | 509 | 00189_update9      | Tue Mar 31 00:00:00 1970 PST
3514  190 |   0 | 00190              | Wed Apr 01 00:00:00 1970 PST
3515  191 |   1 | 00191              | Thu Apr 02 00:00:00 1970 PST
3516  193 | 303 | 00193_update3      | Sat Apr 04 00:00:00 1970 PST
3517  194 |   4 | 00194              | Sun Apr 05 00:00:00 1970 PST
3518  196 |   6 | 00196              | Tue Apr 07 00:00:00 1970 PST
3519  197 | 407 | 00197_update7      | Wed Apr 08 00:00:00 1970 PST
3520  198 |   8 | 00198              | Thu Apr 09 00:00:00 1970 PST
3521  199 | 509 | 00199_update9      | Fri Apr 10 00:00:00 1970 PST
3522  200 |   0 | 00200              | Thu Jan 01 00:00:00 1970 PST
3523  201 |   1 | 00201              | Fri Jan 02 00:00:00 1970 PST
3524  203 | 303 | 00203_update3      | Sun Jan 04 00:00:00 1970 PST
3525  204 |   4 | 00204              | Mon Jan 05 00:00:00 1970 PST
3526  206 |   6 | 00206              | Wed Jan 07 00:00:00 1970 PST
3527  207 | 407 | 00207_update7      | Thu Jan 08 00:00:00 1970 PST
3528  208 |   8 | 00208              | Fri Jan 09 00:00:00 1970 PST
3529  209 | 509 | 00209_update9      | Sat Jan 10 00:00:00 1970 PST
3530  210 |   0 | 00210              | Sun Jan 11 00:00:00 1970 PST
3531  211 |   1 | 00211              | Mon Jan 12 00:00:00 1970 PST
3532  213 | 303 | 00213_update3      | Wed Jan 14 00:00:00 1970 PST
3533  214 |   4 | 00214              | Thu Jan 15 00:00:00 1970 PST
3534  216 |   6 | 00216              | Sat Jan 17 00:00:00 1970 PST
3535  217 | 407 | 00217_update7      | Sun Jan 18 00:00:00 1970 PST
3536  218 |   8 | 00218              | Mon Jan 19 00:00:00 1970 PST
3537  219 | 509 | 00219_update9      | Tue Jan 20 00:00:00 1970 PST
3538  220 |   0 | 00220              | Wed Jan 21 00:00:00 1970 PST
3539  221 |   1 | 00221              | Thu Jan 22 00:00:00 1970 PST
3540  223 | 303 | 00223_update3      | Sat Jan 24 00:00:00 1970 PST
3541  224 |   4 | 00224              | Sun Jan 25 00:00:00 1970 PST
3542  226 |   6 | 00226              | Tue Jan 27 00:00:00 1970 PST
3543  227 | 407 | 00227_update7      | Wed Jan 28 00:00:00 1970 PST
3544  228 |   8 | 00228              | Thu Jan 29 00:00:00 1970 PST
3545  229 | 509 | 00229_update9      | Fri Jan 30 00:00:00 1970 PST
3546  230 |   0 | 00230              | Sat Jan 31 00:00:00 1970 PST
3547  231 |   1 | 00231              | Sun Feb 01 00:00:00 1970 PST
3548  233 | 303 | 00233_update3      | Tue Feb 03 00:00:00 1970 PST
3549  234 |   4 | 00234              | Wed Feb 04 00:00:00 1970 PST
3550  236 |   6 | 00236              | Fri Feb 06 00:00:00 1970 PST
3551  237 | 407 | 00237_update7      | Sat Feb 07 00:00:00 1970 PST
3552  238 |   8 | 00238              | Sun Feb 08 00:00:00 1970 PST
3553  239 | 509 | 00239_update9      | Mon Feb 09 00:00:00 1970 PST
3554  240 |   0 | 00240              | Tue Feb 10 00:00:00 1970 PST
3555  241 |   1 | 00241              | Wed Feb 11 00:00:00 1970 PST
3556  243 | 303 | 00243_update3      | Fri Feb 13 00:00:00 1970 PST
3557  244 |   4 | 00244              | Sat Feb 14 00:00:00 1970 PST
3558  246 |   6 | 00246              | Mon Feb 16 00:00:00 1970 PST
3559  247 | 407 | 00247_update7      | Tue Feb 17 00:00:00 1970 PST
3560  248 |   8 | 00248              | Wed Feb 18 00:00:00 1970 PST
3561  249 | 509 | 00249_update9      | Thu Feb 19 00:00:00 1970 PST
3562  250 |   0 | 00250              | Fri Feb 20 00:00:00 1970 PST
3563  251 |   1 | 00251              | Sat Feb 21 00:00:00 1970 PST
3564  253 | 303 | 00253_update3      | Mon Feb 23 00:00:00 1970 PST
3565  254 |   4 | 00254              | Tue Feb 24 00:00:00 1970 PST
3566  256 |   6 | 00256              | Thu Feb 26 00:00:00 1970 PST
3567  257 | 407 | 00257_update7      | Fri Feb 27 00:00:00 1970 PST
3568  258 |   8 | 00258              | Sat Feb 28 00:00:00 1970 PST
3569  259 | 509 | 00259_update9      | Sun Mar 01 00:00:00 1970 PST
3570  260 |   0 | 00260              | Mon Mar 02 00:00:00 1970 PST
3571  261 |   1 | 00261              | Tue Mar 03 00:00:00 1970 PST
3572  263 | 303 | 00263_update3      | Thu Mar 05 00:00:00 1970 PST
3573  264 |   4 | 00264              | Fri Mar 06 00:00:00 1970 PST
3574  266 |   6 | 00266              | Sun Mar 08 00:00:00 1970 PST
3575  267 | 407 | 00267_update7      | Mon Mar 09 00:00:00 1970 PST
3576  268 |   8 | 00268              | Tue Mar 10 00:00:00 1970 PST
3577  269 | 509 | 00269_update9      | Wed Mar 11 00:00:00 1970 PST
3578  270 |   0 | 00270              | Thu Mar 12 00:00:00 1970 PST
3579  271 |   1 | 00271              | Fri Mar 13 00:00:00 1970 PST
3580  273 | 303 | 00273_update3      | Sun Mar 15 00:00:00 1970 PST
3581  274 |   4 | 00274              | Mon Mar 16 00:00:00 1970 PST
3582  276 |   6 | 00276              | Wed Mar 18 00:00:00 1970 PST
3583  277 | 407 | 00277_update7      | Thu Mar 19 00:00:00 1970 PST
3584  278 |   8 | 00278              | Fri Mar 20 00:00:00 1970 PST
3585  279 | 509 | 00279_update9      | Sat Mar 21 00:00:00 1970 PST
3586  280 |   0 | 00280              | Sun Mar 22 00:00:00 1970 PST
3587  281 |   1 | 00281              | Mon Mar 23 00:00:00 1970 PST
3588  283 | 303 | 00283_update3      | Wed Mar 25 00:00:00 1970 PST
3589  284 |   4 | 00284              | Thu Mar 26 00:00:00 1970 PST
3590  286 |   6 | 00286              | Sat Mar 28 00:00:00 1970 PST
3591  287 | 407 | 00287_update7      | Sun Mar 29 00:00:00 1970 PST
3592  288 |   8 | 00288              | Mon Mar 30 00:00:00 1970 PST
3593  289 | 509 | 00289_update9      | Tue Mar 31 00:00:00 1970 PST
3594  290 |   0 | 00290              | Wed Apr 01 00:00:00 1970 PST
3595  291 |   1 | 00291              | Thu Apr 02 00:00:00 1970 PST
3596  293 | 303 | 00293_update3      | Sat Apr 04 00:00:00 1970 PST
3597  294 |   4 | 00294              | Sun Apr 05 00:00:00 1970 PST
3598  296 |   6 | 00296              | Tue Apr 07 00:00:00 1970 PST
3599  297 | 407 | 00297_update7      | Wed Apr 08 00:00:00 1970 PST
3600  298 |   8 | 00298              | Thu Apr 09 00:00:00 1970 PST
3601  299 | 509 | 00299_update9      | Fri Apr 10 00:00:00 1970 PST
3602  300 |   0 | 00300              | Thu Jan 01 00:00:00 1970 PST
3603  301 |   1 | 00301              | Fri Jan 02 00:00:00 1970 PST
3604  303 | 303 | 00303_update3      | Sun Jan 04 00:00:00 1970 PST
3605  304 |   4 | 00304              | Mon Jan 05 00:00:00 1970 PST
3606  306 |   6 | 00306              | Wed Jan 07 00:00:00 1970 PST
3607  307 | 407 | 00307_update7      | Thu Jan 08 00:00:00 1970 PST
3608  308 |   8 | 00308              | Fri Jan 09 00:00:00 1970 PST
3609  309 | 509 | 00309_update9      | Sat Jan 10 00:00:00 1970 PST
3610  310 |   0 | 00310              | Sun Jan 11 00:00:00 1970 PST
3611  311 |   1 | 00311              | Mon Jan 12 00:00:00 1970 PST
3612  313 | 303 | 00313_update3      | Wed Jan 14 00:00:00 1970 PST
3613  314 |   4 | 00314              | Thu Jan 15 00:00:00 1970 PST
3614  316 |   6 | 00316              | Sat Jan 17 00:00:00 1970 PST
3615  317 | 407 | 00317_update7      | Sun Jan 18 00:00:00 1970 PST
3616  318 |   8 | 00318              | Mon Jan 19 00:00:00 1970 PST
3617  319 | 509 | 00319_update9      | Tue Jan 20 00:00:00 1970 PST
3618  320 |   0 | 00320              | Wed Jan 21 00:00:00 1970 PST
3619  321 |   1 | 00321              | Thu Jan 22 00:00:00 1970 PST
3620  323 | 303 | 00323_update3      | Sat Jan 24 00:00:00 1970 PST
3621  324 |   4 | 00324              | Sun Jan 25 00:00:00 1970 PST
3622  326 |   6 | 00326              | Tue Jan 27 00:00:00 1970 PST
3623  327 | 407 | 00327_update7      | Wed Jan 28 00:00:00 1970 PST
3624  328 |   8 | 00328              | Thu Jan 29 00:00:00 1970 PST
3625  329 | 509 | 00329_update9      | Fri Jan 30 00:00:00 1970 PST
3626  330 |   0 | 00330              | Sat Jan 31 00:00:00 1970 PST
3627  331 |   1 | 00331              | Sun Feb 01 00:00:00 1970 PST
3628  333 | 303 | 00333_update3      | Tue Feb 03 00:00:00 1970 PST
3629  334 |   4 | 00334              | Wed Feb 04 00:00:00 1970 PST
3630  336 |   6 | 00336              | Fri Feb 06 00:00:00 1970 PST
3631  337 | 407 | 00337_update7      | Sat Feb 07 00:00:00 1970 PST
3632  338 |   8 | 00338              | Sun Feb 08 00:00:00 1970 PST
3633  339 | 509 | 00339_update9      | Mon Feb 09 00:00:00 1970 PST
3634  340 |   0 | 00340              | Tue Feb 10 00:00:00 1970 PST
3635  341 |   1 | 00341              | Wed Feb 11 00:00:00 1970 PST
3636  343 | 303 | 00343_update3      | Fri Feb 13 00:00:00 1970 PST
3637  344 |   4 | 00344              | Sat Feb 14 00:00:00 1970 PST
3638  346 |   6 | 00346              | Mon Feb 16 00:00:00 1970 PST
3639  347 | 407 | 00347_update7      | Tue Feb 17 00:00:00 1970 PST
3640  348 |   8 | 00348              | Wed Feb 18 00:00:00 1970 PST
3641  349 | 509 | 00349_update9      | Thu Feb 19 00:00:00 1970 PST
3642  350 |   0 | 00350              | Fri Feb 20 00:00:00 1970 PST
3643  351 |   1 | 00351              | Sat Feb 21 00:00:00 1970 PST
3644  353 | 303 | 00353_update3      | Mon Feb 23 00:00:00 1970 PST
3645  354 |   4 | 00354              | Tue Feb 24 00:00:00 1970 PST
3646  356 |   6 | 00356              | Thu Feb 26 00:00:00 1970 PST
3647  357 | 407 | 00357_update7      | Fri Feb 27 00:00:00 1970 PST
3648  358 |   8 | 00358              | Sat Feb 28 00:00:00 1970 PST
3649  359 | 509 | 00359_update9      | Sun Mar 01 00:00:00 1970 PST
3650  360 |   0 | 00360              | Mon Mar 02 00:00:00 1970 PST
3651  361 |   1 | 00361              | Tue Mar 03 00:00:00 1970 PST
3652  363 | 303 | 00363_update3      | Thu Mar 05 00:00:00 1970 PST
3653  364 |   4 | 00364              | Fri Mar 06 00:00:00 1970 PST
3654  366 |   6 | 00366              | Sun Mar 08 00:00:00 1970 PST
3655  367 | 407 | 00367_update7      | Mon Mar 09 00:00:00 1970 PST
3656  368 |   8 | 00368              | Tue Mar 10 00:00:00 1970 PST
3657  369 | 509 | 00369_update9      | Wed Mar 11 00:00:00 1970 PST
3658  370 |   0 | 00370              | Thu Mar 12 00:00:00 1970 PST
3659  371 |   1 | 00371              | Fri Mar 13 00:00:00 1970 PST
3660  373 | 303 | 00373_update3      | Sun Mar 15 00:00:00 1970 PST
3661  374 |   4 | 00374              | Mon Mar 16 00:00:00 1970 PST
3662  376 |   6 | 00376              | Wed Mar 18 00:00:00 1970 PST
3663  377 | 407 | 00377_update7      | Thu Mar 19 00:00:00 1970 PST
3664  378 |   8 | 00378              | Fri Mar 20 00:00:00 1970 PST
3665  379 | 509 | 00379_update9      | Sat Mar 21 00:00:00 1970 PST
3666  380 |   0 | 00380              | Sun Mar 22 00:00:00 1970 PST
3667  381 |   1 | 00381              | Mon Mar 23 00:00:00 1970 PST
3668  383 | 303 | 00383_update3      | Wed Mar 25 00:00:00 1970 PST
3669  384 |   4 | 00384              | Thu Mar 26 00:00:00 1970 PST
3670  386 |   6 | 00386              | Sat Mar 28 00:00:00 1970 PST
3671  387 | 407 | 00387_update7      | Sun Mar 29 00:00:00 1970 PST
3672  388 |   8 | 00388              | Mon Mar 30 00:00:00 1970 PST
3673  389 | 509 | 00389_update9      | Tue Mar 31 00:00:00 1970 PST
3674  390 |   0 | 00390              | Wed Apr 01 00:00:00 1970 PST
3675  391 |   1 | 00391              | Thu Apr 02 00:00:00 1970 PST
3676  393 | 303 | 00393_update3      | Sat Apr 04 00:00:00 1970 PST
3677  394 |   4 | 00394              | Sun Apr 05 00:00:00 1970 PST
3678  396 |   6 | 00396              | Tue Apr 07 00:00:00 1970 PST
3679  397 | 407 | 00397_update7      | Wed Apr 08 00:00:00 1970 PST
3680  398 |   8 | 00398              | Thu Apr 09 00:00:00 1970 PST
3681  399 | 509 | 00399_update9      | Fri Apr 10 00:00:00 1970 PST
3682  400 |   0 | 00400              | Thu Jan 01 00:00:00 1970 PST
3683  401 |   1 | 00401              | Fri Jan 02 00:00:00 1970 PST
3684  403 | 303 | 00403_update3      | Sun Jan 04 00:00:00 1970 PST
3685  404 |   4 | 00404              | Mon Jan 05 00:00:00 1970 PST
3686  406 |   6 | 00406              | Wed Jan 07 00:00:00 1970 PST
3687  407 | 407 | 00407_update7      | Thu Jan 08 00:00:00 1970 PST
3688  408 |   8 | 00408              | Fri Jan 09 00:00:00 1970 PST
3689  409 | 509 | 00409_update9      | Sat Jan 10 00:00:00 1970 PST
3690  410 |   0 | 00410              | Sun Jan 11 00:00:00 1970 PST
3691  411 |   1 | 00411              | Mon Jan 12 00:00:00 1970 PST
3692  413 | 303 | 00413_update3      | Wed Jan 14 00:00:00 1970 PST
3693  414 |   4 | 00414              | Thu Jan 15 00:00:00 1970 PST
3694  416 |   6 | 00416              | Sat Jan 17 00:00:00 1970 PST
3695  417 | 407 | 00417_update7      | Sun Jan 18 00:00:00 1970 PST
3696  418 |   8 | 00418              | Mon Jan 19 00:00:00 1970 PST
3697  419 | 509 | 00419_update9      | Tue Jan 20 00:00:00 1970 PST
3698  420 |   0 | 00420              | Wed Jan 21 00:00:00 1970 PST
3699  421 |   1 | 00421              | Thu Jan 22 00:00:00 1970 PST
3700  423 | 303 | 00423_update3      | Sat Jan 24 00:00:00 1970 PST
3701  424 |   4 | 00424              | Sun Jan 25 00:00:00 1970 PST
3702  426 |   6 | 00426              | Tue Jan 27 00:00:00 1970 PST
3703  427 | 407 | 00427_update7      | Wed Jan 28 00:00:00 1970 PST
3704  428 |   8 | 00428              | Thu Jan 29 00:00:00 1970 PST
3705  429 | 509 | 00429_update9      | Fri Jan 30 00:00:00 1970 PST
3706  430 |   0 | 00430              | Sat Jan 31 00:00:00 1970 PST
3707  431 |   1 | 00431              | Sun Feb 01 00:00:00 1970 PST
3708  433 | 303 | 00433_update3      | Tue Feb 03 00:00:00 1970 PST
3709  434 |   4 | 00434              | Wed Feb 04 00:00:00 1970 PST
3710  436 |   6 | 00436              | Fri Feb 06 00:00:00 1970 PST
3711  437 | 407 | 00437_update7      | Sat Feb 07 00:00:00 1970 PST
3712  438 |   8 | 00438              | Sun Feb 08 00:00:00 1970 PST
3713  439 | 509 | 00439_update9      | Mon Feb 09 00:00:00 1970 PST
3714  440 |   0 | 00440              | Tue Feb 10 00:00:00 1970 PST
3715  441 |   1 | 00441              | Wed Feb 11 00:00:00 1970 PST
3716  443 | 303 | 00443_update3      | Fri Feb 13 00:00:00 1970 PST
3717  444 |   4 | 00444              | Sat Feb 14 00:00:00 1970 PST
3718  446 |   6 | 00446              | Mon Feb 16 00:00:00 1970 PST
3719  447 | 407 | 00447_update7      | Tue Feb 17 00:00:00 1970 PST
3720  448 |   8 | 00448              | Wed Feb 18 00:00:00 1970 PST
3721  449 | 509 | 00449_update9      | Thu Feb 19 00:00:00 1970 PST
3722  450 |   0 | 00450              | Fri Feb 20 00:00:00 1970 PST
3723  451 |   1 | 00451              | Sat Feb 21 00:00:00 1970 PST
3724  453 | 303 | 00453_update3      | Mon Feb 23 00:00:00 1970 PST
3725  454 |   4 | 00454              | Tue Feb 24 00:00:00 1970 PST
3726  456 |   6 | 00456              | Thu Feb 26 00:00:00 1970 PST
3727  457 | 407 | 00457_update7      | Fri Feb 27 00:00:00 1970 PST
3728  458 |   8 | 00458              | Sat Feb 28 00:00:00 1970 PST
3729  459 | 509 | 00459_update9      | Sun Mar 01 00:00:00 1970 PST
3730  460 |   0 | 00460              | Mon Mar 02 00:00:00 1970 PST
3731  461 |   1 | 00461              | Tue Mar 03 00:00:00 1970 PST
3732  463 | 303 | 00463_update3      | Thu Mar 05 00:00:00 1970 PST
3733  464 |   4 | 00464              | Fri Mar 06 00:00:00 1970 PST
3734  466 |   6 | 00466              | Sun Mar 08 00:00:00 1970 PST
3735  467 | 407 | 00467_update7      | Mon Mar 09 00:00:00 1970 PST
3736  468 |   8 | 00468              | Tue Mar 10 00:00:00 1970 PST
3737  469 | 509 | 00469_update9      | Wed Mar 11 00:00:00 1970 PST
3738  470 |   0 | 00470              | Thu Mar 12 00:00:00 1970 PST
3739  471 |   1 | 00471              | Fri Mar 13 00:00:00 1970 PST
3740  473 | 303 | 00473_update3      | Sun Mar 15 00:00:00 1970 PST
3741  474 |   4 | 00474              | Mon Mar 16 00:00:00 1970 PST
3742  476 |   6 | 00476              | Wed Mar 18 00:00:00 1970 PST
3743  477 | 407 | 00477_update7      | Thu Mar 19 00:00:00 1970 PST
3744  478 |   8 | 00478              | Fri Mar 20 00:00:00 1970 PST
3745  479 | 509 | 00479_update9      | Sat Mar 21 00:00:00 1970 PST
3746  480 |   0 | 00480              | Sun Mar 22 00:00:00 1970 PST
3747  481 |   1 | 00481              | Mon Mar 23 00:00:00 1970 PST
3748  483 | 303 | 00483_update3      | Wed Mar 25 00:00:00 1970 PST
3749  484 |   4 | 00484              | Thu Mar 26 00:00:00 1970 PST
3750  486 |   6 | 00486              | Sat Mar 28 00:00:00 1970 PST
3751  487 | 407 | 00487_update7      | Sun Mar 29 00:00:00 1970 PST
3752  488 |   8 | 00488              | Mon Mar 30 00:00:00 1970 PST
3753  489 | 509 | 00489_update9      | Tue Mar 31 00:00:00 1970 PST
3754  490 |   0 | 00490              | Wed Apr 01 00:00:00 1970 PST
3755  491 |   1 | 00491              | Thu Apr 02 00:00:00 1970 PST
3756  493 | 303 | 00493_update3      | Sat Apr 04 00:00:00 1970 PST
3757  494 |   4 | 00494              | Sun Apr 05 00:00:00 1970 PST
3758  496 |   6 | 00496              | Tue Apr 07 00:00:00 1970 PST
3759  497 | 407 | 00497_update7      | Wed Apr 08 00:00:00 1970 PST
3760  498 |   8 | 00498              | Thu Apr 09 00:00:00 1970 PST
3761  499 | 509 | 00499_update9      | Fri Apr 10 00:00:00 1970 PST
3762  500 |   0 | 00500              | Thu Jan 01 00:00:00 1970 PST
3763  501 |   1 | 00501              | Fri Jan 02 00:00:00 1970 PST
3764  503 | 303 | 00503_update3      | Sun Jan 04 00:00:00 1970 PST
3765  504 |   4 | 00504              | Mon Jan 05 00:00:00 1970 PST
3766  506 |   6 | 00506              | Wed Jan 07 00:00:00 1970 PST
3767  507 | 407 | 00507_update7      | Thu Jan 08 00:00:00 1970 PST
3768  508 |   8 | 00508              | Fri Jan 09 00:00:00 1970 PST
3769  509 | 509 | 00509_update9      | Sat Jan 10 00:00:00 1970 PST
3770  510 |   0 | 00510              | Sun Jan 11 00:00:00 1970 PST
3771  511 |   1 | 00511              | Mon Jan 12 00:00:00 1970 PST
3772  513 | 303 | 00513_update3      | Wed Jan 14 00:00:00 1970 PST
3773  514 |   4 | 00514              | Thu Jan 15 00:00:00 1970 PST
3774  516 |   6 | 00516              | Sat Jan 17 00:00:00 1970 PST
3775  517 | 407 | 00517_update7      | Sun Jan 18 00:00:00 1970 PST
3776  518 |   8 | 00518              | Mon Jan 19 00:00:00 1970 PST
3777  519 | 509 | 00519_update9      | Tue Jan 20 00:00:00 1970 PST
3778  520 |   0 | 00520              | Wed Jan 21 00:00:00 1970 PST
3779  521 |   1 | 00521              | Thu Jan 22 00:00:00 1970 PST
3780  523 | 303 | 00523_update3      | Sat Jan 24 00:00:00 1970 PST
3781  524 |   4 | 00524              | Sun Jan 25 00:00:00 1970 PST
3782  526 |   6 | 00526              | Tue Jan 27 00:00:00 1970 PST
3783  527 | 407 | 00527_update7      | Wed Jan 28 00:00:00 1970 PST
3784  528 |   8 | 00528              | Thu Jan 29 00:00:00 1970 PST
3785  529 | 509 | 00529_update9      | Fri Jan 30 00:00:00 1970 PST
3786  530 |   0 | 00530              | Sat Jan 31 00:00:00 1970 PST
3787  531 |   1 | 00531              | Sun Feb 01 00:00:00 1970 PST
3788  533 | 303 | 00533_update3      | Tue Feb 03 00:00:00 1970 PST
3789  534 |   4 | 00534              | Wed Feb 04 00:00:00 1970 PST
3790  536 |   6 | 00536              | Fri Feb 06 00:00:00 1970 PST
3791  537 | 407 | 00537_update7      | Sat Feb 07 00:00:00 1970 PST
3792  538 |   8 | 00538              | Sun Feb 08 00:00:00 1970 PST
3793  539 | 509 | 00539_update9      | Mon Feb 09 00:00:00 1970 PST
3794  540 |   0 | 00540              | Tue Feb 10 00:00:00 1970 PST
3795  541 |   1 | 00541              | Wed Feb 11 00:00:00 1970 PST
3796  543 | 303 | 00543_update3      | Fri Feb 13 00:00:00 1970 PST
3797  544 |   4 | 00544              | Sat Feb 14 00:00:00 1970 PST
3798  546 |   6 | 00546              | Mon Feb 16 00:00:00 1970 PST
3799  547 | 407 | 00547_update7      | Tue Feb 17 00:00:00 1970 PST
3800  548 |   8 | 00548              | Wed Feb 18 00:00:00 1970 PST
3801  549 | 509 | 00549_update9      | Thu Feb 19 00:00:00 1970 PST
3802  550 |   0 | 00550              | Fri Feb 20 00:00:00 1970 PST
3803  551 |   1 | 00551              | Sat Feb 21 00:00:00 1970 PST
3804  553 | 303 | 00553_update3      | Mon Feb 23 00:00:00 1970 PST
3805  554 |   4 | 00554              | Tue Feb 24 00:00:00 1970 PST
3806  556 |   6 | 00556              | Thu Feb 26 00:00:00 1970 PST
3807  557 | 407 | 00557_update7      | Fri Feb 27 00:00:00 1970 PST
3808  558 |   8 | 00558              | Sat Feb 28 00:00:00 1970 PST
3809  559 | 509 | 00559_update9      | Sun Mar 01 00:00:00 1970 PST
3810  560 |   0 | 00560              | Mon Mar 02 00:00:00 1970 PST
3811  561 |   1 | 00561              | Tue Mar 03 00:00:00 1970 PST
3812  563 | 303 | 00563_update3      | Thu Mar 05 00:00:00 1970 PST
3813  564 |   4 | 00564              | Fri Mar 06 00:00:00 1970 PST
3814  566 |   6 | 00566              | Sun Mar 08 00:00:00 1970 PST
3815  567 | 407 | 00567_update7      | Mon Mar 09 00:00:00 1970 PST
3816  568 |   8 | 00568              | Tue Mar 10 00:00:00 1970 PST
3817  569 | 509 | 00569_update9      | Wed Mar 11 00:00:00 1970 PST
3818  570 |   0 | 00570              | Thu Mar 12 00:00:00 1970 PST
3819  571 |   1 | 00571              | Fri Mar 13 00:00:00 1970 PST
3820  573 | 303 | 00573_update3      | Sun Mar 15 00:00:00 1970 PST
3821  574 |   4 | 00574              | Mon Mar 16 00:00:00 1970 PST
3822  576 |   6 | 00576              | Wed Mar 18 00:00:00 1970 PST
3823  577 | 407 | 00577_update7      | Thu Mar 19 00:00:00 1970 PST
3824  578 |   8 | 00578              | Fri Mar 20 00:00:00 1970 PST
3825  579 | 509 | 00579_update9      | Sat Mar 21 00:00:00 1970 PST
3826  580 |   0 | 00580              | Sun Mar 22 00:00:00 1970 PST
3827  581 |   1 | 00581              | Mon Mar 23 00:00:00 1970 PST
3828  583 | 303 | 00583_update3      | Wed Mar 25 00:00:00 1970 PST
3829  584 |   4 | 00584              | Thu Mar 26 00:00:00 1970 PST
3830  586 |   6 | 00586              | Sat Mar 28 00:00:00 1970 PST
3831  587 | 407 | 00587_update7      | Sun Mar 29 00:00:00 1970 PST
3832  588 |   8 | 00588              | Mon Mar 30 00:00:00 1970 PST
3833  589 | 509 | 00589_update9      | Tue Mar 31 00:00:00 1970 PST
3834  590 |   0 | 00590              | Wed Apr 01 00:00:00 1970 PST
3835  591 |   1 | 00591              | Thu Apr 02 00:00:00 1970 PST
3836  593 | 303 | 00593_update3      | Sat Apr 04 00:00:00 1970 PST
3837  594 |   4 | 00594              | Sun Apr 05 00:00:00 1970 PST
3838  596 |   6 | 00596              | Tue Apr 07 00:00:00 1970 PST
3839  597 | 407 | 00597_update7      | Wed Apr 08 00:00:00 1970 PST
3840  598 |   8 | 00598              | Thu Apr 09 00:00:00 1970 PST
3841  599 | 509 | 00599_update9      | Fri Apr 10 00:00:00 1970 PST
3842  600 |   0 | 00600              | Thu Jan 01 00:00:00 1970 PST
3843  601 |   1 | 00601              | Fri Jan 02 00:00:00 1970 PST
3844  603 | 303 | 00603_update3      | Sun Jan 04 00:00:00 1970 PST
3845  604 |   4 | 00604              | Mon Jan 05 00:00:00 1970 PST
3846  606 |   6 | 00606              | Wed Jan 07 00:00:00 1970 PST
3847  607 | 407 | 00607_update7      | Thu Jan 08 00:00:00 1970 PST
3848  608 |   8 | 00608              | Fri Jan 09 00:00:00 1970 PST
3849  609 | 509 | 00609_update9      | Sat Jan 10 00:00:00 1970 PST
3850  610 |   0 | 00610              | Sun Jan 11 00:00:00 1970 PST
3851  611 |   1 | 00611              | Mon Jan 12 00:00:00 1970 PST
3852  613 | 303 | 00613_update3      | Wed Jan 14 00:00:00 1970 PST
3853  614 |   4 | 00614              | Thu Jan 15 00:00:00 1970 PST
3854  616 |   6 | 00616              | Sat Jan 17 00:00:00 1970 PST
3855  617 | 407 | 00617_update7      | Sun Jan 18 00:00:00 1970 PST
3856  618 |   8 | 00618              | Mon Jan 19 00:00:00 1970 PST
3857  619 | 509 | 00619_update9      | Tue Jan 20 00:00:00 1970 PST
3858  620 |   0 | 00620              | Wed Jan 21 00:00:00 1970 PST
3859  621 |   1 | 00621              | Thu Jan 22 00:00:00 1970 PST
3860  623 | 303 | 00623_update3      | Sat Jan 24 00:00:00 1970 PST
3861  624 |   4 | 00624              | Sun Jan 25 00:00:00 1970 PST
3862  626 |   6 | 00626              | Tue Jan 27 00:00:00 1970 PST
3863  627 | 407 | 00627_update7      | Wed Jan 28 00:00:00 1970 PST
3864  628 |   8 | 00628              | Thu Jan 29 00:00:00 1970 PST
3865  629 | 509 | 00629_update9      | Fri Jan 30 00:00:00 1970 PST
3866  630 |   0 | 00630              | Sat Jan 31 00:00:00 1970 PST
3867  631 |   1 | 00631              | Sun Feb 01 00:00:00 1970 PST
3868  633 | 303 | 00633_update3      | Tue Feb 03 00:00:00 1970 PST
3869  634 |   4 | 00634              | Wed Feb 04 00:00:00 1970 PST
3870  636 |   6 | 00636              | Fri Feb 06 00:00:00 1970 PST
3871  637 | 407 | 00637_update7      | Sat Feb 07 00:00:00 1970 PST
3872  638 |   8 | 00638              | Sun Feb 08 00:00:00 1970 PST
3873  639 | 509 | 00639_update9      | Mon Feb 09 00:00:00 1970 PST
3874  640 |   0 | 00640              | Tue Feb 10 00:00:00 1970 PST
3875  641 |   1 | 00641              | Wed Feb 11 00:00:00 1970 PST
3876  643 | 303 | 00643_update3      | Fri Feb 13 00:00:00 1970 PST
3877  644 |   4 | 00644              | Sat Feb 14 00:00:00 1970 PST
3878  646 |   6 | 00646              | Mon Feb 16 00:00:00 1970 PST
3879  647 | 407 | 00647_update7      | Tue Feb 17 00:00:00 1970 PST
3880  648 |   8 | 00648              | Wed Feb 18 00:00:00 1970 PST
3881  649 | 509 | 00649_update9      | Thu Feb 19 00:00:00 1970 PST
3882  650 |   0 | 00650              | Fri Feb 20 00:00:00 1970 PST
3883  651 |   1 | 00651              | Sat Feb 21 00:00:00 1970 PST
3884  653 | 303 | 00653_update3      | Mon Feb 23 00:00:00 1970 PST
3885  654 |   4 | 00654              | Tue Feb 24 00:00:00 1970 PST
3886  656 |   6 | 00656              | Thu Feb 26 00:00:00 1970 PST
3887  657 | 407 | 00657_update7      | Fri Feb 27 00:00:00 1970 PST
3888  658 |   8 | 00658              | Sat Feb 28 00:00:00 1970 PST
3889  659 | 509 | 00659_update9      | Sun Mar 01 00:00:00 1970 PST
3890  660 |   0 | 00660              | Mon Mar 02 00:00:00 1970 PST
3891  661 |   1 | 00661              | Tue Mar 03 00:00:00 1970 PST
3892  663 | 303 | 00663_update3      | Thu Mar 05 00:00:00 1970 PST
3893  664 |   4 | 00664              | Fri Mar 06 00:00:00 1970 PST
3894  666 |   6 | 00666              | Sun Mar 08 00:00:00 1970 PST
3895  667 | 407 | 00667_update7      | Mon Mar 09 00:00:00 1970 PST
3896  668 |   8 | 00668              | Tue Mar 10 00:00:00 1970 PST
3897  669 | 509 | 00669_update9      | Wed Mar 11 00:00:00 1970 PST
3898  670 |   0 | 00670              | Thu Mar 12 00:00:00 1970 PST
3899  671 |   1 | 00671              | Fri Mar 13 00:00:00 1970 PST
3900  673 | 303 | 00673_update3      | Sun Mar 15 00:00:00 1970 PST
3901  674 |   4 | 00674              | Mon Mar 16 00:00:00 1970 PST
3902  676 |   6 | 00676              | Wed Mar 18 00:00:00 1970 PST
3903  677 | 407 | 00677_update7      | Thu Mar 19 00:00:00 1970 PST
3904  678 |   8 | 00678              | Fri Mar 20 00:00:00 1970 PST
3905  679 | 509 | 00679_update9      | Sat Mar 21 00:00:00 1970 PST
3906  680 |   0 | 00680              | Sun Mar 22 00:00:00 1970 PST
3907  681 |   1 | 00681              | Mon Mar 23 00:00:00 1970 PST
3908  683 | 303 | 00683_update3      | Wed Mar 25 00:00:00 1970 PST
3909  684 |   4 | 00684              | Thu Mar 26 00:00:00 1970 PST
3910  686 |   6 | 00686              | Sat Mar 28 00:00:00 1970 PST
3911  687 | 407 | 00687_update7      | Sun Mar 29 00:00:00 1970 PST
3912  688 |   8 | 00688              | Mon Mar 30 00:00:00 1970 PST
3913  689 | 509 | 00689_update9      | Tue Mar 31 00:00:00 1970 PST
3914  690 |   0 | 00690              | Wed Apr 01 00:00:00 1970 PST
3915  691 |   1 | 00691              | Thu Apr 02 00:00:00 1970 PST
3916  693 | 303 | 00693_update3      | Sat Apr 04 00:00:00 1970 PST
3917  694 |   4 | 00694              | Sun Apr 05 00:00:00 1970 PST
3918  696 |   6 | 00696              | Tue Apr 07 00:00:00 1970 PST
3919  697 | 407 | 00697_update7      | Wed Apr 08 00:00:00 1970 PST
3920  698 |   8 | 00698              | Thu Apr 09 00:00:00 1970 PST
3921  699 | 509 | 00699_update9      | Fri Apr 10 00:00:00 1970 PST
3922  700 |   0 | 00700              | Thu Jan 01 00:00:00 1970 PST
3923  701 |   1 | 00701              | Fri Jan 02 00:00:00 1970 PST
3924  703 | 303 | 00703_update3      | Sun Jan 04 00:00:00 1970 PST
3925  704 |   4 | 00704              | Mon Jan 05 00:00:00 1970 PST
3926  706 |   6 | 00706              | Wed Jan 07 00:00:00 1970 PST
3927  707 | 407 | 00707_update7      | Thu Jan 08 00:00:00 1970 PST
3928  708 |   8 | 00708              | Fri Jan 09 00:00:00 1970 PST
3929  709 | 509 | 00709_update9      | Sat Jan 10 00:00:00 1970 PST
3930  710 |   0 | 00710              | Sun Jan 11 00:00:00 1970 PST
3931  711 |   1 | 00711              | Mon Jan 12 00:00:00 1970 PST
3932  713 | 303 | 00713_update3      | Wed Jan 14 00:00:00 1970 PST
3933  714 |   4 | 00714              | Thu Jan 15 00:00:00 1970 PST
3934  716 |   6 | 00716              | Sat Jan 17 00:00:00 1970 PST
3935  717 | 407 | 00717_update7      | Sun Jan 18 00:00:00 1970 PST
3936  718 |   8 | 00718              | Mon Jan 19 00:00:00 1970 PST
3937  719 | 509 | 00719_update9      | Tue Jan 20 00:00:00 1970 PST
3938  720 |   0 | 00720              | Wed Jan 21 00:00:00 1970 PST
3939  721 |   1 | 00721              | Thu Jan 22 00:00:00 1970 PST
3940  723 | 303 | 00723_update3      | Sat Jan 24 00:00:00 1970 PST
3941  724 |   4 | 00724              | Sun Jan 25 00:00:00 1970 PST
3942  726 |   6 | 00726              | Tue Jan 27 00:00:00 1970 PST
3943  727 | 407 | 00727_update7      | Wed Jan 28 00:00:00 1970 PST
3944  728 |   8 | 00728              | Thu Jan 29 00:00:00 1970 PST
3945  729 | 509 | 00729_update9      | Fri Jan 30 00:00:00 1970 PST
3946  730 |   0 | 00730              | Sat Jan 31 00:00:00 1970 PST
3947  731 |   1 | 00731              | Sun Feb 01 00:00:00 1970 PST
3948  733 | 303 | 00733_update3      | Tue Feb 03 00:00:00 1970 PST
3949  734 |   4 | 00734              | Wed Feb 04 00:00:00 1970 PST
3950  736 |   6 | 00736              | Fri Feb 06 00:00:00 1970 PST
3951  737 | 407 | 00737_update7      | Sat Feb 07 00:00:00 1970 PST
3952  738 |   8 | 00738              | Sun Feb 08 00:00:00 1970 PST
3953  739 | 509 | 00739_update9      | Mon Feb 09 00:00:00 1970 PST
3954  740 |   0 | 00740              | Tue Feb 10 00:00:00 1970 PST
3955  741 |   1 | 00741              | Wed Feb 11 00:00:00 1970 PST
3956  743 | 303 | 00743_update3      | Fri Feb 13 00:00:00 1970 PST
3957  744 |   4 | 00744              | Sat Feb 14 00:00:00 1970 PST
3958  746 |   6 | 00746              | Mon Feb 16 00:00:00 1970 PST
3959  747 | 407 | 00747_update7      | Tue Feb 17 00:00:00 1970 PST
3960  748 |   8 | 00748              | Wed Feb 18 00:00:00 1970 PST
3961  749 | 509 | 00749_update9      | Thu Feb 19 00:00:00 1970 PST
3962  750 |   0 | 00750              | Fri Feb 20 00:00:00 1970 PST
3963  751 |   1 | 00751              | Sat Feb 21 00:00:00 1970 PST
3964  753 | 303 | 00753_update3      | Mon Feb 23 00:00:00 1970 PST
3965  754 |   4 | 00754              | Tue Feb 24 00:00:00 1970 PST
3966  756 |   6 | 00756              | Thu Feb 26 00:00:00 1970 PST
3967  757 | 407 | 00757_update7      | Fri Feb 27 00:00:00 1970 PST
3968  758 |   8 | 00758              | Sat Feb 28 00:00:00 1970 PST
3969  759 | 509 | 00759_update9      | Sun Mar 01 00:00:00 1970 PST
3970  760 |   0 | 00760              | Mon Mar 02 00:00:00 1970 PST
3971  761 |   1 | 00761              | Tue Mar 03 00:00:00 1970 PST
3972  763 | 303 | 00763_update3      | Thu Mar 05 00:00:00 1970 PST
3973  764 |   4 | 00764              | Fri Mar 06 00:00:00 1970 PST
3974  766 |   6 | 00766              | Sun Mar 08 00:00:00 1970 PST
3975  767 | 407 | 00767_update7      | Mon Mar 09 00:00:00 1970 PST
3976  768 |   8 | 00768              | Tue Mar 10 00:00:00 1970 PST
3977  769 | 509 | 00769_update9      | Wed Mar 11 00:00:00 1970 PST
3978  770 |   0 | 00770              | Thu Mar 12 00:00:00 1970 PST
3979  771 |   1 | 00771              | Fri Mar 13 00:00:00 1970 PST
3980  773 | 303 | 00773_update3      | Sun Mar 15 00:00:00 1970 PST
3981  774 |   4 | 00774              | Mon Mar 16 00:00:00 1970 PST
3982  776 |   6 | 00776              | Wed Mar 18 00:00:00 1970 PST
3983  777 | 407 | 00777_update7      | Thu Mar 19 00:00:00 1970 PST
3984  778 |   8 | 00778              | Fri Mar 20 00:00:00 1970 PST
3985  779 | 509 | 00779_update9      | Sat Mar 21 00:00:00 1970 PST
3986  780 |   0 | 00780              | Sun Mar 22 00:00:00 1970 PST
3987  781 |   1 | 00781              | Mon Mar 23 00:00:00 1970 PST
3988  783 | 303 | 00783_update3      | Wed Mar 25 00:00:00 1970 PST
3989  784 |   4 | 00784              | Thu Mar 26 00:00:00 1970 PST
3990  786 |   6 | 00786              | Sat Mar 28 00:00:00 1970 PST
3991  787 | 407 | 00787_update7      | Sun Mar 29 00:00:00 1970 PST
3992  788 |   8 | 00788              | Mon Mar 30 00:00:00 1970 PST
3993  789 | 509 | 00789_update9      | Tue Mar 31 00:00:00 1970 PST
3994  790 |   0 | 00790              | Wed Apr 01 00:00:00 1970 PST
3995  791 |   1 | 00791              | Thu Apr 02 00:00:00 1970 PST
3996  793 | 303 | 00793_update3      | Sat Apr 04 00:00:00 1970 PST
3997  794 |   4 | 00794              | Sun Apr 05 00:00:00 1970 PST
3998  796 |   6 | 00796              | Tue Apr 07 00:00:00 1970 PST
3999  797 | 407 | 00797_update7      | Wed Apr 08 00:00:00 1970 PST
4000  798 |   8 | 00798              | Thu Apr 09 00:00:00 1970 PST
4001  799 | 509 | 00799_update9      | Fri Apr 10 00:00:00 1970 PST
4002  800 |   0 | 00800              | Thu Jan 01 00:00:00 1970 PST
4003  801 |   1 | 00801              | Fri Jan 02 00:00:00 1970 PST
4004  803 | 303 | 00803_update3      | Sun Jan 04 00:00:00 1970 PST
4005  804 |   4 | 00804              | Mon Jan 05 00:00:00 1970 PST
4006  806 |   6 | 00806              | Wed Jan 07 00:00:00 1970 PST
4007  807 | 407 | 00807_update7      | Thu Jan 08 00:00:00 1970 PST
4008  808 |   8 | 00808              | Fri Jan 09 00:00:00 1970 PST
4009  809 | 509 | 00809_update9      | Sat Jan 10 00:00:00 1970 PST
4010  810 |   0 | 00810              | Sun Jan 11 00:00:00 1970 PST
4011  811 |   1 | 00811              | Mon Jan 12 00:00:00 1970 PST
4012  813 | 303 | 00813_update3      | Wed Jan 14 00:00:00 1970 PST
4013  814 |   4 | 00814              | Thu Jan 15 00:00:00 1970 PST
4014  816 |   6 | 00816              | Sat Jan 17 00:00:00 1970 PST
4015  817 | 407 | 00817_update7      | Sun Jan 18 00:00:00 1970 PST
4016  818 |   8 | 00818              | Mon Jan 19 00:00:00 1970 PST
4017  819 | 509 | 00819_update9      | Tue Jan 20 00:00:00 1970 PST
4018  820 |   0 | 00820              | Wed Jan 21 00:00:00 1970 PST
4019  821 |   1 | 00821              | Thu Jan 22 00:00:00 1970 PST
4020  823 | 303 | 00823_update3      | Sat Jan 24 00:00:00 1970 PST
4021  824 |   4 | 00824              | Sun Jan 25 00:00:00 1970 PST
4022  826 |   6 | 00826              | Tue Jan 27 00:00:00 1970 PST
4023  827 | 407 | 00827_update7      | Wed Jan 28 00:00:00 1970 PST
4024  828 |   8 | 00828              | Thu Jan 29 00:00:00 1970 PST
4025  829 | 509 | 00829_update9      | Fri Jan 30 00:00:00 1970 PST
4026  830 |   0 | 00830              | Sat Jan 31 00:00:00 1970 PST
4027  831 |   1 | 00831              | Sun Feb 01 00:00:00 1970 PST
4028  833 | 303 | 00833_update3      | Tue Feb 03 00:00:00 1970 PST
4029  834 |   4 | 00834              | Wed Feb 04 00:00:00 1970 PST
4030  836 |   6 | 00836              | Fri Feb 06 00:00:00 1970 PST
4031  837 | 407 | 00837_update7      | Sat Feb 07 00:00:00 1970 PST
4032  838 |   8 | 00838              | Sun Feb 08 00:00:00 1970 PST
4033  839 | 509 | 00839_update9      | Mon Feb 09 00:00:00 1970 PST
4034  840 |   0 | 00840              | Tue Feb 10 00:00:00 1970 PST
4035  841 |   1 | 00841              | Wed Feb 11 00:00:00 1970 PST
4036  843 | 303 | 00843_update3      | Fri Feb 13 00:00:00 1970 PST
4037  844 |   4 | 00844              | Sat Feb 14 00:00:00 1970 PST
4038  846 |   6 | 00846              | Mon Feb 16 00:00:00 1970 PST
4039  847 | 407 | 00847_update7      | Tue Feb 17 00:00:00 1970 PST
4040  848 |   8 | 00848              | Wed Feb 18 00:00:00 1970 PST
4041  849 | 509 | 00849_update9      | Thu Feb 19 00:00:00 1970 PST
4042  850 |   0 | 00850              | Fri Feb 20 00:00:00 1970 PST
4043  851 |   1 | 00851              | Sat Feb 21 00:00:00 1970 PST
4044  853 | 303 | 00853_update3      | Mon Feb 23 00:00:00 1970 PST
4045  854 |   4 | 00854              | Tue Feb 24 00:00:00 1970 PST
4046  856 |   6 | 00856              | Thu Feb 26 00:00:00 1970 PST
4047  857 | 407 | 00857_update7      | Fri Feb 27 00:00:00 1970 PST
4048  858 |   8 | 00858              | Sat Feb 28 00:00:00 1970 PST
4049  859 | 509 | 00859_update9      | Sun Mar 01 00:00:00 1970 PST
4050  860 |   0 | 00860              | Mon Mar 02 00:00:00 1970 PST
4051  861 |   1 | 00861              | Tue Mar 03 00:00:00 1970 PST
4052  863 | 303 | 00863_update3      | Thu Mar 05 00:00:00 1970 PST
4053  864 |   4 | 00864              | Fri Mar 06 00:00:00 1970 PST
4054  866 |   6 | 00866              | Sun Mar 08 00:00:00 1970 PST
4055  867 | 407 | 00867_update7      | Mon Mar 09 00:00:00 1970 PST
4056  868 |   8 | 00868              | Tue Mar 10 00:00:00 1970 PST
4057  869 | 509 | 00869_update9      | Wed Mar 11 00:00:00 1970 PST
4058  870 |   0 | 00870              | Thu Mar 12 00:00:00 1970 PST
4059  871 |   1 | 00871              | Fri Mar 13 00:00:00 1970 PST
4060  873 | 303 | 00873_update3      | Sun Mar 15 00:00:00 1970 PST
4061  874 |   4 | 00874              | Mon Mar 16 00:00:00 1970 PST
4062  876 |   6 | 00876              | Wed Mar 18 00:00:00 1970 PST
4063  877 | 407 | 00877_update7      | Thu Mar 19 00:00:00 1970 PST
4064  878 |   8 | 00878              | Fri Mar 20 00:00:00 1970 PST
4065  879 | 509 | 00879_update9      | Sat Mar 21 00:00:00 1970 PST
4066  880 |   0 | 00880              | Sun Mar 22 00:00:00 1970 PST
4067  881 |   1 | 00881              | Mon Mar 23 00:00:00 1970 PST
4068  883 | 303 | 00883_update3      | Wed Mar 25 00:00:00 1970 PST
4069  884 |   4 | 00884              | Thu Mar 26 00:00:00 1970 PST
4070  886 |   6 | 00886              | Sat Mar 28 00:00:00 1970 PST
4071  887 | 407 | 00887_update7      | Sun Mar 29 00:00:00 1970 PST
4072  888 |   8 | 00888              | Mon Mar 30 00:00:00 1970 PST
4073  889 | 509 | 00889_update9      | Tue Mar 31 00:00:00 1970 PST
4074  890 |   0 | 00890              | Wed Apr 01 00:00:00 1970 PST
4075  891 |   1 | 00891              | Thu Apr 02 00:00:00 1970 PST
4076  893 | 303 | 00893_update3      | Sat Apr 04 00:00:00 1970 PST
4077  894 |   4 | 00894              | Sun Apr 05 00:00:00 1970 PST
4078  896 |   6 | 00896              | Tue Apr 07 00:00:00 1970 PST
4079  897 | 407 | 00897_update7      | Wed Apr 08 00:00:00 1970 PST
4080  898 |   8 | 00898              | Thu Apr 09 00:00:00 1970 PST
4081  899 | 509 | 00899_update9      | Fri Apr 10 00:00:00 1970 PST
4082  900 |   0 | 00900              | Thu Jan 01 00:00:00 1970 PST
4083  901 |   1 | 00901              | Fri Jan 02 00:00:00 1970 PST
4084  903 | 303 | 00903_update3      | Sun Jan 04 00:00:00 1970 PST
4085  904 |   4 | 00904              | Mon Jan 05 00:00:00 1970 PST
4086  906 |   6 | 00906              | Wed Jan 07 00:00:00 1970 PST
4087  907 | 407 | 00907_update7      | Thu Jan 08 00:00:00 1970 PST
4088  908 |   8 | 00908              | Fri Jan 09 00:00:00 1970 PST
4089  909 | 509 | 00909_update9      | Sat Jan 10 00:00:00 1970 PST
4090  910 |   0 | 00910              | Sun Jan 11 00:00:00 1970 PST
4091  911 |   1 | 00911              | Mon Jan 12 00:00:00 1970 PST
4092  913 | 303 | 00913_update3      | Wed Jan 14 00:00:00 1970 PST
4093  914 |   4 | 00914              | Thu Jan 15 00:00:00 1970 PST
4094  916 |   6 | 00916              | Sat Jan 17 00:00:00 1970 PST
4095  917 | 407 | 00917_update7      | Sun Jan 18 00:00:00 1970 PST
4096  918 |   8 | 00918              | Mon Jan 19 00:00:00 1970 PST
4097  919 | 509 | 00919_update9      | Tue Jan 20 00:00:00 1970 PST
4098  920 |   0 | 00920              | Wed Jan 21 00:00:00 1970 PST
4099  921 |   1 | 00921              | Thu Jan 22 00:00:00 1970 PST
4100  923 | 303 | 00923_update3      | Sat Jan 24 00:00:00 1970 PST
4101  924 |   4 | 00924              | Sun Jan 25 00:00:00 1970 PST
4102  926 |   6 | 00926              | Tue Jan 27 00:00:00 1970 PST
4103  927 | 407 | 00927_update7      | Wed Jan 28 00:00:00 1970 PST
4104  928 |   8 | 00928              | Thu Jan 29 00:00:00 1970 PST
4105  929 | 509 | 00929_update9      | Fri Jan 30 00:00:00 1970 PST
4106  930 |   0 | 00930              | Sat Jan 31 00:00:00 1970 PST
4107  931 |   1 | 00931              | Sun Feb 01 00:00:00 1970 PST
4108  933 | 303 | 00933_update3      | Tue Feb 03 00:00:00 1970 PST
4109  934 |   4 | 00934              | Wed Feb 04 00:00:00 1970 PST
4110  936 |   6 | 00936              | Fri Feb 06 00:00:00 1970 PST
4111  937 | 407 | 00937_update7      | Sat Feb 07 00:00:00 1970 PST
4112  938 |   8 | 00938              | Sun Feb 08 00:00:00 1970 PST
4113  939 | 509 | 00939_update9      | Mon Feb 09 00:00:00 1970 PST
4114  940 |   0 | 00940              | Tue Feb 10 00:00:00 1970 PST
4115  941 |   1 | 00941              | Wed Feb 11 00:00:00 1970 PST
4116  943 | 303 | 00943_update3      | Fri Feb 13 00:00:00 1970 PST
4117  944 |   4 | 00944              | Sat Feb 14 00:00:00 1970 PST
4118  946 |   6 | 00946              | Mon Feb 16 00:00:00 1970 PST
4119  947 | 407 | 00947_update7      | Tue Feb 17 00:00:00 1970 PST
4120  948 |   8 | 00948              | Wed Feb 18 00:00:00 1970 PST
4121  949 | 509 | 00949_update9      | Thu Feb 19 00:00:00 1970 PST
4122  950 |   0 | 00950              | Fri Feb 20 00:00:00 1970 PST
4123  951 |   1 | 00951              | Sat Feb 21 00:00:00 1970 PST
4124  953 | 303 | 00953_update3      | Mon Feb 23 00:00:00 1970 PST
4125  954 |   4 | 00954              | Tue Feb 24 00:00:00 1970 PST
4126  956 |   6 | 00956              | Thu Feb 26 00:00:00 1970 PST
4127  957 | 407 | 00957_update7      | Fri Feb 27 00:00:00 1970 PST
4128  958 |   8 | 00958              | Sat Feb 28 00:00:00 1970 PST
4129  959 | 509 | 00959_update9      | Sun Mar 01 00:00:00 1970 PST
4130  960 |   0 | 00960              | Mon Mar 02 00:00:00 1970 PST
4131  961 |   1 | 00961              | Tue Mar 03 00:00:00 1970 PST
4132  963 | 303 | 00963_update3      | Thu Mar 05 00:00:00 1970 PST
4133  964 |   4 | 00964              | Fri Mar 06 00:00:00 1970 PST
4134  966 |   6 | 00966              | Sun Mar 08 00:00:00 1970 PST
4135  967 | 407 | 00967_update7      | Mon Mar 09 00:00:00 1970 PST
4136  968 |   8 | 00968              | Tue Mar 10 00:00:00 1970 PST
4137  969 | 509 | 00969_update9      | Wed Mar 11 00:00:00 1970 PST
4138  970 |   0 | 00970              | Thu Mar 12 00:00:00 1970 PST
4139  971 |   1 | 00971              | Fri Mar 13 00:00:00 1970 PST
4140  973 | 303 | 00973_update3      | Sun Mar 15 00:00:00 1970 PST
4141  974 |   4 | 00974              | Mon Mar 16 00:00:00 1970 PST
4142  976 |   6 | 00976              | Wed Mar 18 00:00:00 1970 PST
4143  977 | 407 | 00977_update7      | Thu Mar 19 00:00:00 1970 PST
4144  978 |   8 | 00978              | Fri Mar 20 00:00:00 1970 PST
4145  979 | 509 | 00979_update9      | Sat Mar 21 00:00:00 1970 PST
4146  980 |   0 | 00980              | Sun Mar 22 00:00:00 1970 PST
4147  981 |   1 | 00981              | Mon Mar 23 00:00:00 1970 PST
4148  983 | 303 | 00983_update3      | Wed Mar 25 00:00:00 1970 PST
4149  984 |   4 | 00984              | Thu Mar 26 00:00:00 1970 PST
4150  986 |   6 | 00986              | Sat Mar 28 00:00:00 1970 PST
4151  987 | 407 | 00987_update7      | Sun Mar 29 00:00:00 1970 PST
4152  988 |   8 | 00988              | Mon Mar 30 00:00:00 1970 PST
4153  989 | 509 | 00989_update9      | Tue Mar 31 00:00:00 1970 PST
4154  990 |   0 | 00990              | Wed Apr 01 00:00:00 1970 PST
4155  991 |   1 | 00991              | Thu Apr 02 00:00:00 1970 PST
4156  993 | 303 | 00993_update3      | Sat Apr 04 00:00:00 1970 PST
4157  994 |   4 | 00994              | Sun Apr 05 00:00:00 1970 PST
4158  996 |   6 | 00996              | Tue Apr 07 00:00:00 1970 PST
4159  997 | 407 | 00997_update7      | Wed Apr 08 00:00:00 1970 PST
4160  998 |   8 | 00998              | Thu Apr 09 00:00:00 1970 PST
4161  999 | 509 | 00999_update9      | Fri Apr 10 00:00:00 1970 PST
4162 1000 |   0 | 01000              | Thu Jan 01 00:00:00 1970 PST
4163 1001 | 101 | 0000100001         |
4164 1003 | 403 | 0000300003_update3 |
4165 1004 | 104 | 0000400004         |
4166 1006 | 106 | 0000600006         |
4167 1007 | 507 | 0000700007_update7 |
4168 1008 | 108 | 0000800008         |
4169 1009 | 609 | 0000900009_update9 |
4170 1010 | 100 | 0001000010         |
4171 1011 | 101 | 0001100011         |
4172 1013 | 403 | 0001300013_update3 |
4173 1014 | 104 | 0001400014         |
4174 1016 | 106 | 0001600016         |
4175 1017 | 507 | 0001700017_update7 |
4176 1018 | 108 | 0001800018         |
4177 1019 | 609 | 0001900019_update9 |
4178 1020 | 100 | 0002000020         |
4179 1101 | 201 | aaa                |
4180 1103 | 503 | ccc_update3        |
4181 1104 | 204 | ddd                |
4182(819 rows)
4183
4184EXPLAIN (verbose, costs off)
4185INSERT INTO ft2 (c1,c2,c3) VALUES (9999,999,'foo') RETURNING tableoid::regclass;
4186                                                                                           QUERY PLAN
4187-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4188 Insert on public.ft2
4189   Output: (tableoid)::regclass
4190   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)
4191   ->  Result
4192         Output: 9999, 999, NULL::integer, 'foo'::text, NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2       '::character(10), NULL::user_enum
4193(5 rows)
4194
4195INSERT INTO ft2 (c1,c2,c3) VALUES (9999,999,'foo') RETURNING tableoid::regclass;
4196 tableoid
4197----------
4198 ft2
4199(1 row)
4200
4201EXPLAIN (verbose, costs off)
4202UPDATE ft2 SET c3 = 'bar' WHERE c1 = 9999 RETURNING tableoid::regclass;             -- can be pushed down
4203                                     QUERY PLAN
4204------------------------------------------------------------------------------------
4205 Update on public.ft2
4206   Output: (tableoid)::regclass
4207   ->  Foreign Update on public.ft2
4208         Remote SQL: UPDATE "S 1"."T 1" SET c3 = 'bar'::text WHERE (("C 1" = 9999))
4209(4 rows)
4210
4211UPDATE ft2 SET c3 = 'bar' WHERE c1 = 9999 RETURNING tableoid::regclass;
4212 tableoid
4213----------
4214 ft2
4215(1 row)
4216
4217EXPLAIN (verbose, costs off)
4218DELETE FROM ft2 WHERE c1 = 9999 RETURNING tableoid::regclass;                       -- can be pushed down
4219                             QUERY PLAN
4220--------------------------------------------------------------------
4221 Delete on public.ft2
4222   Output: (tableoid)::regclass
4223   ->  Foreign Delete on public.ft2
4224         Remote SQL: DELETE FROM "S 1"."T 1" WHERE (("C 1" = 9999))
4225(4 rows)
4226
4227DELETE FROM ft2 WHERE c1 = 9999 RETURNING tableoid::regclass;
4228 tableoid
4229----------
4230 ft2
4231(1 row)
4232
4233-- Test UPDATE with a MULTIEXPR sub-select
4234-- (maybe someday this'll be remotely executable, but not today)
4235EXPLAIN (verbose, costs off)
4236UPDATE ft2 AS target SET (c2, c7) = (
4237    SELECT c2 * 10, c7
4238        FROM ft2 AS src
4239        WHERE target.c1 = src.c1
4240) WHERE c1 > 1100;
4241                                                                    QUERY PLAN
4242---------------------------------------------------------------------------------------------------------------------------------------------------
4243 Update on public.ft2 target
4244   Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c7 = $3 WHERE ctid = $1
4245   ->  Foreign Scan on public.ft2 target
4246         Output: target.c1, $1, NULL::integer, target.c3, target.c4, target.c5, target.c6, $2, target.c8, (SubPlan 1 (returns $1,$2)), target.ctid
4247         Remote SQL: SELECT "C 1", c3, c4, c5, c6, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 1100)) FOR UPDATE
4248         SubPlan 1 (returns $1,$2)
4249           ->  Foreign Scan on public.ft2 src
4250                 Output: (src.c2 * 10), src.c7
4251                 Remote SQL: SELECT c2, c7 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
4252(9 rows)
4253
4254UPDATE ft2 AS target SET (c2, c7) = (
4255    SELECT c2 * 10, c7
4256        FROM ft2 AS src
4257        WHERE target.c1 = src.c1
4258) WHERE c1 > 1100;
4259UPDATE ft2 AS target SET (c2) = (
4260    SELECT c2 / 10
4261        FROM ft2 AS src
4262        WHERE target.c1 = src.c1
4263) WHERE c1 > 1100;
4264-- Test that trigger on remote table works as expected
4265CREATE OR REPLACE FUNCTION "S 1".F_BRTRIG() RETURNS trigger AS $$
4266BEGIN
4267    NEW.c3 = NEW.c3 || '_trig_update';
4268    RETURN NEW;
4269END;
4270$$ LANGUAGE plpgsql;
4271CREATE TRIGGER t1_br_insert BEFORE INSERT OR UPDATE
4272    ON "S 1"."T 1" FOR EACH ROW EXECUTE PROCEDURE "S 1".F_BRTRIG();
4273INSERT INTO ft2 (c1,c2,c3) VALUES (1208, 818, 'fff') RETURNING *;
4274  c1  | c2  |       c3        | c4 | c5 | c6 |     c7     | c8
4275------+-----+-----------------+----+----+----+------------+----
4276 1208 | 818 | fff_trig_update |    |    |    | ft2        |
4277(1 row)
4278
4279INSERT INTO ft2 (c1,c2,c3,c6) VALUES (1218, 818, 'ggg', '(--;') RETURNING *;
4280  c1  | c2  |       c3        | c4 | c5 |  c6  |     c7     | c8
4281------+-----+-----------------+----+----+------+------------+----
4282 1218 | 818 | ggg_trig_update |    |    | (--; | ft2        |
4283(1 row)
4284
4285UPDATE ft2 SET c2 = c2 + 600 WHERE c1 % 10 = 8 AND c1 < 1200 RETURNING *;
4286  c1  | c2  |           c3           |              c4              |            c5            | c6 |     c7     | c8
4287------+-----+------------------------+------------------------------+--------------------------+----+------------+-----
4288    8 | 608 | 00008_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
4289   18 | 608 | 00018_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
4290   28 | 608 | 00028_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
4291   38 | 608 | 00038_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
4292   48 | 608 | 00048_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
4293   58 | 608 | 00058_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
4294   68 | 608 | 00068_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
4295   78 | 608 | 00078_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
4296   88 | 608 | 00088_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
4297   98 | 608 | 00098_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
4298  108 | 608 | 00108_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
4299  118 | 608 | 00118_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
4300  128 | 608 | 00128_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
4301  138 | 608 | 00138_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
4302  148 | 608 | 00148_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
4303  158 | 608 | 00158_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
4304  168 | 608 | 00168_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
4305  178 | 608 | 00178_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
4306  188 | 608 | 00188_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
4307  198 | 608 | 00198_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
4308  208 | 608 | 00208_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
4309  218 | 608 | 00218_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
4310  228 | 608 | 00228_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
4311  238 | 608 | 00238_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
4312  248 | 608 | 00248_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
4313  258 | 608 | 00258_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
4314  268 | 608 | 00268_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
4315  278 | 608 | 00278_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
4316  288 | 608 | 00288_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
4317  298 | 608 | 00298_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
4318  308 | 608 | 00308_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
4319  318 | 608 | 00318_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
4320  328 | 608 | 00328_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
4321  338 | 608 | 00338_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
4322  348 | 608 | 00348_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
4323  358 | 608 | 00358_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
4324  368 | 608 | 00368_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
4325  378 | 608 | 00378_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
4326  388 | 608 | 00388_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
4327  398 | 608 | 00398_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
4328  408 | 608 | 00408_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
4329  418 | 608 | 00418_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
4330  428 | 608 | 00428_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
4331  438 | 608 | 00438_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
4332  448 | 608 | 00448_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
4333  458 | 608 | 00458_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
4334  468 | 608 | 00468_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
4335  478 | 608 | 00478_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
4336  488 | 608 | 00488_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
4337  498 | 608 | 00498_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
4338  508 | 608 | 00508_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
4339  518 | 608 | 00518_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
4340  528 | 608 | 00528_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
4341  538 | 608 | 00538_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
4342  548 | 608 | 00548_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
4343  558 | 608 | 00558_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
4344  568 | 608 | 00568_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
4345  578 | 608 | 00578_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
4346  588 | 608 | 00588_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
4347  598 | 608 | 00598_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
4348  608 | 608 | 00608_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
4349  618 | 608 | 00618_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
4350  628 | 608 | 00628_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
4351  638 | 608 | 00638_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
4352  648 | 608 | 00648_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
4353  658 | 608 | 00658_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
4354  668 | 608 | 00668_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
4355  678 | 608 | 00678_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
4356  688 | 608 | 00688_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
4357  698 | 608 | 00698_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
4358  708 | 608 | 00708_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
4359  718 | 608 | 00718_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
4360  728 | 608 | 00728_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
4361  738 | 608 | 00738_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
4362  748 | 608 | 00748_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
4363  758 | 608 | 00758_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
4364  768 | 608 | 00768_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
4365  778 | 608 | 00778_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
4366  788 | 608 | 00788_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
4367  798 | 608 | 00798_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
4368  808 | 608 | 00808_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
4369  818 | 608 | 00818_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
4370  828 | 608 | 00828_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
4371  838 | 608 | 00838_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
4372  848 | 608 | 00848_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
4373  858 | 608 | 00858_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
4374  868 | 608 | 00868_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
4375  878 | 608 | 00878_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
4376  888 | 608 | 00888_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
4377  898 | 608 | 00898_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
4378  908 | 608 | 00908_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
4379  918 | 608 | 00918_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
4380  928 | 608 | 00928_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
4381  938 | 608 | 00938_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
4382  948 | 608 | 00948_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
4383  958 | 608 | 00958_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
4384  968 | 608 | 00968_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
4385  978 | 608 | 00978_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
4386  988 | 608 | 00988_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
4387  998 | 608 | 00998_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
4388 1008 | 708 | 0000800008_trig_update |                              |                          |    | ft2        |
4389 1018 | 708 | 0001800018_trig_update |                              |                          |    | ft2        |
4390(102 rows)
4391
4392-- Test errors thrown on remote side during update
4393ALTER TABLE "S 1"."T 1" ADD CONSTRAINT c2positive CHECK (c2 >= 0);
4394INSERT INTO ft1(c1, c2) VALUES(11, 12);  -- duplicate key
4395ERROR:  duplicate key value violates unique constraint "t1_pkey"
4396DETAIL:  Key ("C 1")=(11) already exists.
4397CONTEXT:  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)
4398INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT DO NOTHING; -- works
4399INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO NOTHING; -- unsupported
4400ERROR:  there is no unique or exclusion constraint matching the ON CONFLICT specification
4401INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO UPDATE SET c3 = 'ffg'; -- unsupported
4402ERROR:  there is no unique or exclusion constraint matching the ON CONFLICT specification
4403INSERT INTO ft1(c1, c2) VALUES(1111, -2);  -- c2positive
4404ERROR:  new row for relation "T 1" violates check constraint "c2positive"
4405DETAIL:  Failing row contains (1111, -2, null, null, null, null, ft1       , null).
4406CONTEXT:  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)
4407UPDATE ft1 SET c2 = -c2 WHERE c1 = 1;  -- c2positive
4408ERROR:  new row for relation "T 1" violates check constraint "c2positive"
4409DETAIL:  Failing row contains (1, -1, 00001_trig_update, 1970-01-02 08:00:00+00, 1970-01-02 00:00:00, 1, 1         , foo).
4410CONTEXT:  Remote SQL command: UPDATE "S 1"."T 1" SET c2 = (- c2) WHERE (("C 1" = 1))
4411-- Test savepoint/rollback behavior
4412select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
4413 c2  | count
4414-----+-------
4415   0 |   100
4416   1 |   100
4417   4 |   100
4418   6 |   100
4419 100 |     2
4420 101 |     2
4421 104 |     2
4422 106 |     2
4423 201 |     1
4424 204 |     1
4425 303 |   100
4426 403 |     2
4427 407 |   100
4428(13 rows)
4429
4430select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
4431 c2  | count
4432-----+-------
4433   0 |   100
4434   1 |   100
4435   4 |   100
4436   6 |   100
4437 100 |     2
4438 101 |     2
4439 104 |     2
4440 106 |     2
4441 201 |     1
4442 204 |     1
4443 303 |   100
4444 403 |     2
4445 407 |   100
4446(13 rows)
4447
4448begin;
4449update ft2 set c2 = 42 where c2 = 0;
4450select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
4451 c2  | count
4452-----+-------
4453   1 |   100
4454   4 |   100
4455   6 |   100
4456  42 |   100
4457 100 |     2
4458 101 |     2
4459 104 |     2
4460 106 |     2
4461 201 |     1
4462 204 |     1
4463 303 |   100
4464 403 |     2
4465 407 |   100
4466(13 rows)
4467
4468savepoint s1;
4469update ft2 set c2 = 44 where c2 = 4;
4470select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
4471 c2  | count
4472-----+-------
4473   1 |   100
4474   6 |   100
4475  42 |   100
4476  44 |   100
4477 100 |     2
4478 101 |     2
4479 104 |     2
4480 106 |     2
4481 201 |     1
4482 204 |     1
4483 303 |   100
4484 403 |     2
4485 407 |   100
4486(13 rows)
4487
4488release savepoint s1;
4489select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
4490 c2  | count
4491-----+-------
4492   1 |   100
4493   6 |   100
4494  42 |   100
4495  44 |   100
4496 100 |     2
4497 101 |     2
4498 104 |     2
4499 106 |     2
4500 201 |     1
4501 204 |     1
4502 303 |   100
4503 403 |     2
4504 407 |   100
4505(13 rows)
4506
4507savepoint s2;
4508update ft2 set c2 = 46 where c2 = 6;
4509select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
4510 c2  | count
4511-----+-------
4512   1 |   100
4513  42 |   100
4514  44 |   100
4515  46 |   100
4516 100 |     2
4517 101 |     2
4518 104 |     2
4519 106 |     2
4520 201 |     1
4521 204 |     1
4522 303 |   100
4523 403 |     2
4524 407 |   100
4525(13 rows)
4526
4527rollback to savepoint s2;
4528select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
4529 c2  | count
4530-----+-------
4531   1 |   100
4532   6 |   100
4533  42 |   100
4534  44 |   100
4535 100 |     2
4536 101 |     2
4537 104 |     2
4538 106 |     2
4539 201 |     1
4540 204 |     1
4541 303 |   100
4542 403 |     2
4543 407 |   100
4544(13 rows)
4545
4546release savepoint s2;
4547select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
4548 c2  | count
4549-----+-------
4550   1 |   100
4551   6 |   100
4552  42 |   100
4553  44 |   100
4554 100 |     2
4555 101 |     2
4556 104 |     2
4557 106 |     2
4558 201 |     1
4559 204 |     1
4560 303 |   100
4561 403 |     2
4562 407 |   100
4563(13 rows)
4564
4565savepoint s3;
4566update ft2 set c2 = -2 where c2 = 42 and c1 = 10; -- fail on remote side
4567ERROR:  new row for relation "T 1" violates check constraint "c2positive"
4568DETAIL:  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).
4569CONTEXT:  Remote SQL command: UPDATE "S 1"."T 1" SET c2 = (-2) WHERE ((c2 = 42)) AND (("C 1" = 10))
4570rollback to savepoint s3;
4571select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
4572 c2  | count
4573-----+-------
4574   1 |   100
4575   6 |   100
4576  42 |   100
4577  44 |   100
4578 100 |     2
4579 101 |     2
4580 104 |     2
4581 106 |     2
4582 201 |     1
4583 204 |     1
4584 303 |   100
4585 403 |     2
4586 407 |   100
4587(13 rows)
4588
4589release savepoint s3;
4590select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
4591 c2  | count
4592-----+-------
4593   1 |   100
4594   6 |   100
4595  42 |   100
4596  44 |   100
4597 100 |     2
4598 101 |     2
4599 104 |     2
4600 106 |     2
4601 201 |     1
4602 204 |     1
4603 303 |   100
4604 403 |     2
4605 407 |   100
4606(13 rows)
4607
4608-- none of the above is committed yet remotely
4609select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
4610 c2  | count
4611-----+-------
4612   0 |   100
4613   1 |   100
4614   4 |   100
4615   6 |   100
4616 100 |     2
4617 101 |     2
4618 104 |     2
4619 106 |     2
4620 201 |     1
4621 204 |     1
4622 303 |   100
4623 403 |     2
4624 407 |   100
4625(13 rows)
4626
4627commit;
4628select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
4629 c2  | count
4630-----+-------
4631   1 |   100
4632   6 |   100
4633  42 |   100
4634  44 |   100
4635 100 |     2
4636 101 |     2
4637 104 |     2
4638 106 |     2
4639 201 |     1
4640 204 |     1
4641 303 |   100
4642 403 |     2
4643 407 |   100
4644(13 rows)
4645
4646select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
4647 c2  | count
4648-----+-------
4649   1 |   100
4650   6 |   100
4651  42 |   100
4652  44 |   100
4653 100 |     2
4654 101 |     2
4655 104 |     2
4656 106 |     2
4657 201 |     1
4658 204 |     1
4659 303 |   100
4660 403 |     2
4661 407 |   100
4662(13 rows)
4663
4664-- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs
4665-- FIRST behavior here.
4666-- ORDER BY DESC NULLS LAST options
4667EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10;
4668                                                           QUERY PLAN
4669---------------------------------------------------------------------------------------------------------------------------------
4670 Limit
4671   Output: c1, c2, c3, c4, c5, c6, c7, c8
4672   ->  Foreign Scan on public.ft1
4673         Output: c1, c2, c3, c4, c5, c6, c7, c8
4674         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
4675(5 rows)
4676
4677SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795  LIMIT 10;
4678  c1  | c2  |         c3         |              c4              |            c5            |  c6  |     c7     | c8
4679------+-----+--------------------+------------------------------+--------------------------+------+------------+-----
4680  960 |  42 | 00960_trig_update  | Mon Mar 02 00:00:00 1970 PST | Mon Mar 02 00:00:00 1970 | 0    | 0          | foo
4681  970 |  42 | 00970_trig_update  | Thu Mar 12 00:00:00 1970 PST | Thu Mar 12 00:00:00 1970 | 0    | 0          | foo
4682  980 |  42 | 00980_trig_update  | Sun Mar 22 00:00:00 1970 PST | Sun Mar 22 00:00:00 1970 | 0    | 0          | foo
4683  990 |  42 | 00990_trig_update  | Wed Apr 01 00:00:00 1970 PST | Wed Apr 01 00:00:00 1970 | 0    | 0          | foo
4684 1000 |  42 | 01000_trig_update  | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0    | 0          | foo
4685 1218 | 818 | ggg_trig_update    |                              |                          | (--; | ft2        |
4686 1001 | 101 | 0000100001         |                              |                          |      | ft2        |
4687 1003 | 403 | 0000300003_update3 |                              |                          |      | ft2        |
4688 1004 | 104 | 0000400004         |                              |                          |      | ft2        |
4689 1006 | 106 | 0000600006         |                              |                          |      | ft2        |
4690(10 rows)
4691
4692-- ORDER BY DESC NULLS FIRST options
4693EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
4694                                                            QUERY PLAN
4695----------------------------------------------------------------------------------------------------------------------------------
4696 Limit
4697   Output: c1, c2, c3, c4, c5, c6, c7, c8
4698   ->  Foreign Scan on public.ft1
4699         Output: c1, c2, c3, c4, c5, c6, c7, c8
4700         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
4701(5 rows)
4702
4703SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
4704  c1  | c2  |       c3        |              c4              |            c5            | c6 |     c7     | c8
4705------+-----+-----------------+------------------------------+--------------------------+----+------------+-----
4706 1020 | 100 | 0002000020      |                              |                          |    | ft2        |
4707 1101 | 201 | aaa             |                              |                          |    | ft2        |
4708 1103 | 503 | ccc_update3     |                              |                          |    | ft2        |
4709 1104 | 204 | ddd             |                              |                          |    | ft2        |
4710 1208 | 818 | fff_trig_update |                              |                          |    | ft2        |
4711    9 | 509 | 00009_update9   | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | ft2        | foo
4712   19 | 509 | 00019_update9   | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9  | ft2        | foo
4713   29 | 509 | 00029_update9   | Fri Jan 30 00:00:00 1970 PST | Fri Jan 30 00:00:00 1970 | 9  | ft2        | foo
4714   39 | 509 | 00039_update9   | Mon Feb 09 00:00:00 1970 PST | Mon Feb 09 00:00:00 1970 | 9  | ft2        | foo
4715   49 | 509 | 00049_update9   | Thu Feb 19 00:00:00 1970 PST | Thu Feb 19 00:00:00 1970 | 9  | ft2        | foo
4716(10 rows)
4717
4718-- ORDER BY ASC NULLS FIRST options
4719EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
4720                                                           QUERY PLAN
4721---------------------------------------------------------------------------------------------------------------------------------
4722 Limit
4723   Output: c1, c2, c3, c4, c5, c6, c7, c8
4724   ->  Foreign Scan on public.ft1
4725         Output: c1, c2, c3, c4, c5, c6, c7, c8
4726         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
4727(5 rows)
4728
4729SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
4730  c1  | c2  |        c3         |              c4              |            c5            |  c6  |     c7     | c8
4731------+-----+-------------------+------------------------------+--------------------------+------+------------+-----
4732 1020 | 100 | 0002000020        |                              |                          |      | ft2        |
4733 1101 | 201 | aaa               |                              |                          |      | ft2        |
4734 1103 | 503 | ccc_update3       |                              |                          |      | ft2        |
4735 1104 | 204 | ddd               |                              |                          |      | ft2        |
4736 1208 | 818 | fff_trig_update   |                              |                          |      | ft2        |
4737 1218 | 818 | ggg_trig_update   |                              |                          | (--; | ft2        |
4738   10 |  42 | 00010_trig_update | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0    | 0          | foo
4739   20 |  42 | 00020_trig_update | Wed Jan 21 00:00:00 1970 PST | Wed Jan 21 00:00:00 1970 | 0    | 0          | foo
4740   30 |  42 | 00030_trig_update | Sat Jan 31 00:00:00 1970 PST | Sat Jan 31 00:00:00 1970 | 0    | 0          | foo
4741   40 |  42 | 00040_trig_update | Tue Feb 10 00:00:00 1970 PST | Tue Feb 10 00:00:00 1970 | 0    | 0          | foo
4742(10 rows)
4743
4744-- ===================================================================
4745-- test check constraints
4746-- ===================================================================
4747-- Consistent check constraints provide consistent results
4748ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK (c2 >= 0);
4749EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0;
4750                            QUERY PLAN
4751-------------------------------------------------------------------
4752 Aggregate
4753   Output: count(*)
4754   ->  Foreign Scan on public.ft1
4755         Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE ((c2 < 0))
4756(4 rows)
4757
4758SELECT count(*) FROM ft1 WHERE c2 < 0;
4759 count
4760-------
4761     0
4762(1 row)
4763
4764SET constraint_exclusion = 'on';
4765EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0;
4766           QUERY PLAN
4767--------------------------------
4768 Aggregate
4769   Output: count(*)
4770   ->  Result
4771         One-Time Filter: false
4772(4 rows)
4773
4774SELECT count(*) FROM ft1 WHERE c2 < 0;
4775 count
4776-------
4777     0
4778(1 row)
4779
4780RESET constraint_exclusion;
4781-- check constraint is enforced on the remote side, not locally
4782INSERT INTO ft1(c1, c2) VALUES(1111, -2);  -- c2positive
4783ERROR:  new row for relation "T 1" violates check constraint "c2positive"
4784DETAIL:  Failing row contains (1111, -2, null, null, null, null, ft1       , null).
4785CONTEXT:  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)
4786UPDATE ft1 SET c2 = -c2 WHERE c1 = 1;  -- c2positive
4787ERROR:  new row for relation "T 1" violates check constraint "c2positive"
4788DETAIL:  Failing row contains (1, -1, 00001_trig_update, 1970-01-02 08:00:00+00, 1970-01-02 00:00:00, 1, 1         , foo).
4789CONTEXT:  Remote SQL command: UPDATE "S 1"."T 1" SET c2 = (- c2) WHERE (("C 1" = 1))
4790ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive;
4791-- But inconsistent check constraints provide inconsistent results
4792ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK (c2 < 0);
4793EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0;
4794                             QUERY PLAN
4795--------------------------------------------------------------------
4796 Aggregate
4797   Output: count(*)
4798   ->  Foreign Scan on public.ft1
4799         Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE ((c2 >= 0))
4800(4 rows)
4801
4802SELECT count(*) FROM ft1 WHERE c2 >= 0;
4803 count
4804-------
4805   821
4806(1 row)
4807
4808SET constraint_exclusion = 'on';
4809EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0;
4810           QUERY PLAN
4811--------------------------------
4812 Aggregate
4813   Output: count(*)
4814   ->  Result
4815         One-Time Filter: false
4816(4 rows)
4817
4818SELECT count(*) FROM ft1 WHERE c2 >= 0;
4819 count
4820-------
4821     0
4822(1 row)
4823
4824RESET constraint_exclusion;
4825-- local check constraint is not actually enforced
4826INSERT INTO ft1(c1, c2) VALUES(1111, 2);
4827UPDATE ft1 SET c2 = c2 + 1 WHERE c1 = 1;
4828ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2negative;
4829-- ===================================================================
4830-- test WITH CHECK OPTION constraints
4831-- ===================================================================
4832CREATE TABLE base_tbl (a int, b int);
4833CREATE FOREIGN TABLE foreign_tbl (a int, b int)
4834  SERVER loopback OPTIONS(table_name 'base_tbl');
4835CREATE VIEW rw_view AS SELECT * FROM foreign_tbl
4836  WHERE a < b WITH CHECK OPTION;
4837\d+ rw_view
4838                View "public.rw_view"
4839 Column |  Type   | Modifiers | Storage | Description
4840--------+---------+-----------+---------+-------------
4841 a      | integer |           | plain   |
4842 b      | integer |           | plain   |
4843View definition:
4844 SELECT foreign_tbl.a,
4845    foreign_tbl.b
4846   FROM foreign_tbl
4847  WHERE foreign_tbl.a < foreign_tbl.b;
4848Options: check_option=cascaded
4849
4850INSERT INTO rw_view VALUES (0, 10); -- ok
4851INSERT INTO rw_view VALUES (10, 0); -- should fail
4852ERROR:  new row violates check option for view "rw_view"
4853DETAIL:  Failing row contains (10, 0).
4854EXPLAIN (VERBOSE, COSTS OFF)
4855UPDATE rw_view SET b = 20 WHERE a = 0; -- not pushed down
4856                                            QUERY PLAN
4857--------------------------------------------------------------------------------------------------
4858 Update on public.foreign_tbl
4859   Remote SQL: UPDATE public.base_tbl SET b = $2 WHERE ctid = $1
4860   ->  Foreign Scan on public.foreign_tbl
4861         Output: foreign_tbl.a, 20, foreign_tbl.ctid
4862         Remote SQL: SELECT a, ctid FROM public.base_tbl WHERE ((a < b)) AND ((a = 0)) FOR UPDATE
4863(5 rows)
4864
4865UPDATE rw_view SET b = 20 WHERE a = 0; -- ok
4866EXPLAIN (VERBOSE, COSTS OFF)
4867UPDATE rw_view SET b = -20 WHERE a = 0; -- not pushed down
4868                                            QUERY PLAN
4869--------------------------------------------------------------------------------------------------
4870 Update on public.foreign_tbl
4871   Remote SQL: UPDATE public.base_tbl SET b = $2 WHERE ctid = $1
4872   ->  Foreign Scan on public.foreign_tbl
4873         Output: foreign_tbl.a, '-20'::integer, foreign_tbl.ctid
4874         Remote SQL: SELECT a, ctid FROM public.base_tbl WHERE ((a < b)) AND ((a = 0)) FOR UPDATE
4875(5 rows)
4876
4877UPDATE rw_view SET b = -20 WHERE a = 0; -- should fail
4878ERROR:  new row violates check option for view "rw_view"
4879DETAIL:  Failing row contains (0, -20).
4880SELECT * FROM foreign_tbl;
4881 a | b
4882---+----
4883 0 | 20
4884(1 row)
4885
4886DROP FOREIGN TABLE foreign_tbl CASCADE;
4887NOTICE:  drop cascades to view rw_view
4888DROP TABLE base_tbl;
4889-- ===================================================================
4890-- test serial columns (ie, sequence-based defaults)
4891-- ===================================================================
4892create table loc1 (f1 serial, f2 text);
4893create foreign table rem1 (f1 serial, f2 text)
4894  server loopback options(table_name 'loc1');
4895select pg_catalog.setval('rem1_f1_seq', 10, false);
4896 setval
4897--------
4898     10
4899(1 row)
4900
4901insert into loc1(f2) values('hi');
4902insert into rem1(f2) values('hi remote');
4903insert into loc1(f2) values('bye');
4904insert into rem1(f2) values('bye remote');
4905select * from loc1;
4906 f1 |     f2
4907----+------------
4908  1 | hi
4909 10 | hi remote
4910  2 | bye
4911 11 | bye remote
4912(4 rows)
4913
4914select * from rem1;
4915 f1 |     f2
4916----+------------
4917  1 | hi
4918 10 | hi remote
4919  2 | bye
4920 11 | bye remote
4921(4 rows)
4922
4923-- ===================================================================
4924-- test local triggers
4925-- ===================================================================
4926-- Trigger functions "borrowed" from triggers regress test.
4927CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$
4928BEGIN
4929	RAISE NOTICE 'trigger_func(%) called: action = %, when = %, level = %',
4930		TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL;
4931	RETURN NULL;
4932END;$$;
4933CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE ON rem1
4934	FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
4935CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE ON rem1
4936	FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
4937CREATE OR REPLACE FUNCTION trigger_data()  RETURNS trigger
4938LANGUAGE plpgsql AS $$
4939
4940declare
4941	oldnew text[];
4942	relid text;
4943    argstr text;
4944begin
4945
4946	relid := TG_relid::regclass;
4947	argstr := '';
4948	for i in 0 .. TG_nargs - 1 loop
4949		if i > 0 then
4950			argstr := argstr || ', ';
4951		end if;
4952		argstr := argstr || TG_argv[i];
4953	end loop;
4954
4955    RAISE NOTICE '%(%) % % % ON %',
4956		tg_name, argstr, TG_when, TG_level, TG_OP, relid;
4957    oldnew := '{}'::text[];
4958	if TG_OP != 'INSERT' then
4959		oldnew := array_append(oldnew, format('OLD: %s', OLD));
4960	end if;
4961
4962	if TG_OP != 'DELETE' then
4963		oldnew := array_append(oldnew, format('NEW: %s', NEW));
4964	end if;
4965
4966    RAISE NOTICE '%', array_to_string(oldnew, ',');
4967
4968	if TG_OP = 'DELETE' then
4969		return OLD;
4970	else
4971		return NEW;
4972	end if;
4973end;
4974$$;
4975-- Test basic functionality
4976CREATE TRIGGER trig_row_before
4977BEFORE INSERT OR UPDATE OR DELETE ON rem1
4978FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
4979CREATE TRIGGER trig_row_after
4980AFTER INSERT OR UPDATE OR DELETE ON rem1
4981FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
4982delete from rem1;
4983NOTICE:  trigger_func(<NULL>) called: action = DELETE, when = BEFORE, level = STATEMENT
4984NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
4985NOTICE:  OLD: (1,hi)
4986NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
4987NOTICE:  OLD: (10,"hi remote")
4988NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
4989NOTICE:  OLD: (2,bye)
4990NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
4991NOTICE:  OLD: (11,"bye remote")
4992NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
4993NOTICE:  OLD: (1,hi)
4994NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
4995NOTICE:  OLD: (10,"hi remote")
4996NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
4997NOTICE:  OLD: (2,bye)
4998NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
4999NOTICE:  OLD: (11,"bye remote")
5000NOTICE:  trigger_func(<NULL>) called: action = DELETE, when = AFTER, level = STATEMENT
5001insert into rem1 values(1,'insert');
5002NOTICE:  trigger_func(<NULL>) called: action = INSERT, when = BEFORE, level = STATEMENT
5003NOTICE:  trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
5004NOTICE:  NEW: (1,insert)
5005NOTICE:  trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
5006NOTICE:  NEW: (1,insert)
5007NOTICE:  trigger_func(<NULL>) called: action = INSERT, when = AFTER, level = STATEMENT
5008update rem1 set f2  = 'update' where f1 = 1;
5009NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = BEFORE, level = STATEMENT
5010NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
5011NOTICE:  OLD: (1,insert),NEW: (1,update)
5012NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
5013NOTICE:  OLD: (1,insert),NEW: (1,update)
5014NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
5015update rem1 set f2 = f2 || f2;
5016NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = BEFORE, level = STATEMENT
5017NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
5018NOTICE:  OLD: (1,update),NEW: (1,updateupdate)
5019NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
5020NOTICE:  OLD: (1,update),NEW: (1,updateupdate)
5021NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
5022-- cleanup
5023DROP TRIGGER trig_row_before ON rem1;
5024DROP TRIGGER trig_row_after ON rem1;
5025DROP TRIGGER trig_stmt_before ON rem1;
5026DROP TRIGGER trig_stmt_after ON rem1;
5027DELETE from rem1;
5028-- Test WHEN conditions
5029CREATE TRIGGER trig_row_before_insupd
5030BEFORE INSERT OR UPDATE ON rem1
5031FOR EACH ROW
5032WHEN (NEW.f2 like '%update%')
5033EXECUTE PROCEDURE trigger_data(23,'skidoo');
5034CREATE TRIGGER trig_row_after_insupd
5035AFTER INSERT OR UPDATE ON rem1
5036FOR EACH ROW
5037WHEN (NEW.f2 like '%update%')
5038EXECUTE PROCEDURE trigger_data(23,'skidoo');
5039-- Insert or update not matching: nothing happens
5040INSERT INTO rem1 values(1, 'insert');
5041UPDATE rem1 set f2 = 'test';
5042-- Insert or update matching: triggers are fired
5043INSERT INTO rem1 values(2, 'update');
5044NOTICE:  trig_row_before_insupd(23, skidoo) BEFORE ROW INSERT ON rem1
5045NOTICE:  NEW: (2,update)
5046NOTICE:  trig_row_after_insupd(23, skidoo) AFTER ROW INSERT ON rem1
5047NOTICE:  NEW: (2,update)
5048UPDATE rem1 set f2 = 'update update' where f1 = '2';
5049NOTICE:  trig_row_before_insupd(23, skidoo) BEFORE ROW UPDATE ON rem1
5050NOTICE:  OLD: (2,update),NEW: (2,"update update")
5051NOTICE:  trig_row_after_insupd(23, skidoo) AFTER ROW UPDATE ON rem1
5052NOTICE:  OLD: (2,update),NEW: (2,"update update")
5053CREATE TRIGGER trig_row_before_delete
5054BEFORE DELETE ON rem1
5055FOR EACH ROW
5056WHEN (OLD.f2 like '%update%')
5057EXECUTE PROCEDURE trigger_data(23,'skidoo');
5058CREATE TRIGGER trig_row_after_delete
5059AFTER DELETE ON rem1
5060FOR EACH ROW
5061WHEN (OLD.f2 like '%update%')
5062EXECUTE PROCEDURE trigger_data(23,'skidoo');
5063-- Trigger is fired for f1=2, not for f1=1
5064DELETE FROM rem1;
5065NOTICE:  trig_row_before_delete(23, skidoo) BEFORE ROW DELETE ON rem1
5066NOTICE:  OLD: (2,"update update")
5067NOTICE:  trig_row_after_delete(23, skidoo) AFTER ROW DELETE ON rem1
5068NOTICE:  OLD: (2,"update update")
5069-- cleanup
5070DROP TRIGGER trig_row_before_insupd ON rem1;
5071DROP TRIGGER trig_row_after_insupd ON rem1;
5072DROP TRIGGER trig_row_before_delete ON rem1;
5073DROP TRIGGER trig_row_after_delete ON rem1;
5074-- Test various RETURN statements in BEFORE triggers.
5075CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$
5076  BEGIN
5077    NEW.f2 := NEW.f2 || ' triggered !';
5078    RETURN NEW;
5079  END
5080$$ language plpgsql;
5081CREATE TRIGGER trig_row_before_insupd
5082BEFORE INSERT OR UPDATE ON rem1
5083FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
5084-- The new values should have 'triggered' appended
5085INSERT INTO rem1 values(1, 'insert');
5086SELECT * from loc1;
5087 f1 |         f2
5088----+--------------------
5089  1 | insert triggered !
5090(1 row)
5091
5092INSERT INTO rem1 values(2, 'insert') RETURNING f2;
5093         f2
5094--------------------
5095 insert triggered !
5096(1 row)
5097
5098SELECT * from loc1;
5099 f1 |         f2
5100----+--------------------
5101  1 | insert triggered !
5102  2 | insert triggered !
5103(2 rows)
5104
5105UPDATE rem1 set f2 = '';
5106SELECT * from loc1;
5107 f1 |      f2
5108----+--------------
5109  1 |  triggered !
5110  2 |  triggered !
5111(2 rows)
5112
5113UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
5114         f2
5115--------------------
5116 skidoo triggered !
5117 skidoo triggered !
5118(2 rows)
5119
5120SELECT * from loc1;
5121 f1 |         f2
5122----+--------------------
5123  1 | skidoo triggered !
5124  2 | skidoo triggered !
5125(2 rows)
5126
5127EXPLAIN (verbose, costs off)
5128UPDATE rem1 set f1 = 10;          -- all columns should be transmitted
5129                              QUERY PLAN
5130-----------------------------------------------------------------------
5131 Update on public.rem1
5132   Remote SQL: UPDATE public.loc1 SET f1 = $2, f2 = $3 WHERE ctid = $1
5133   ->  Foreign Scan on public.rem1
5134         Output: 10, f2, ctid, rem1.*
5135         Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
5136(5 rows)
5137
5138UPDATE rem1 set f1 = 10;
5139SELECT * from loc1;
5140 f1 |               f2
5141----+--------------------------------
5142 10 | skidoo triggered ! triggered !
5143 10 | skidoo triggered ! triggered !
5144(2 rows)
5145
5146DELETE FROM rem1;
5147-- Add a second trigger, to check that the changes are propagated correctly
5148-- from trigger to trigger
5149CREATE TRIGGER trig_row_before_insupd2
5150BEFORE INSERT OR UPDATE ON rem1
5151FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
5152INSERT INTO rem1 values(1, 'insert');
5153SELECT * from loc1;
5154 f1 |               f2
5155----+--------------------------------
5156  1 | insert triggered ! triggered !
5157(1 row)
5158
5159INSERT INTO rem1 values(2, 'insert') RETURNING f2;
5160               f2
5161--------------------------------
5162 insert triggered ! triggered !
5163(1 row)
5164
5165SELECT * from loc1;
5166 f1 |               f2
5167----+--------------------------------
5168  1 | insert triggered ! triggered !
5169  2 | insert triggered ! triggered !
5170(2 rows)
5171
5172UPDATE rem1 set f2 = '';
5173SELECT * from loc1;
5174 f1 |            f2
5175----+--------------------------
5176  1 |  triggered ! triggered !
5177  2 |  triggered ! triggered !
5178(2 rows)
5179
5180UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
5181               f2
5182--------------------------------
5183 skidoo triggered ! triggered !
5184 skidoo triggered ! triggered !
5185(2 rows)
5186
5187SELECT * from loc1;
5188 f1 |               f2
5189----+--------------------------------
5190  1 | skidoo triggered ! triggered !
5191  2 | skidoo triggered ! triggered !
5192(2 rows)
5193
5194DROP TRIGGER trig_row_before_insupd ON rem1;
5195DROP TRIGGER trig_row_before_insupd2 ON rem1;
5196DELETE from rem1;
5197INSERT INTO rem1 VALUES (1, 'test');
5198-- Test with a trigger returning NULL
5199CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$
5200  BEGIN
5201    RETURN NULL;
5202  END
5203$$ language plpgsql;
5204CREATE TRIGGER trig_null
5205BEFORE INSERT OR UPDATE OR DELETE ON rem1
5206FOR EACH ROW EXECUTE PROCEDURE trig_null();
5207-- Nothing should have changed.
5208INSERT INTO rem1 VALUES (2, 'test2');
5209SELECT * from loc1;
5210 f1 |  f2
5211----+------
5212  1 | test
5213(1 row)
5214
5215UPDATE rem1 SET f2 = 'test2';
5216SELECT * from loc1;
5217 f1 |  f2
5218----+------
5219  1 | test
5220(1 row)
5221
5222DELETE from rem1;
5223SELECT * from loc1;
5224 f1 |  f2
5225----+------
5226  1 | test
5227(1 row)
5228
5229DROP TRIGGER trig_null ON rem1;
5230DELETE from rem1;
5231-- Test a combination of local and remote triggers
5232CREATE TRIGGER trig_row_before
5233BEFORE INSERT OR UPDATE OR DELETE ON rem1
5234FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
5235CREATE TRIGGER trig_row_after
5236AFTER INSERT OR UPDATE OR DELETE ON rem1
5237FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
5238CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON loc1
5239FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
5240INSERT INTO rem1(f2) VALUES ('test');
5241NOTICE:  trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
5242NOTICE:  NEW: (12,test)
5243NOTICE:  trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
5244NOTICE:  NEW: (12,"test triggered !")
5245UPDATE rem1 SET f2 = 'testo';
5246NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
5247NOTICE:  OLD: (12,"test triggered !"),NEW: (12,testo)
5248NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
5249NOTICE:  OLD: (12,"test triggered !"),NEW: (12,"testo triggered !")
5250-- Test returning a system attribute
5251INSERT INTO rem1(f2) VALUES ('test') RETURNING ctid;
5252NOTICE:  trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
5253NOTICE:  NEW: (13,test)
5254NOTICE:  trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
5255NOTICE:  NEW: (13,"test triggered !")
5256  ctid
5257--------
5258 (0,29)
5259(1 row)
5260
5261-- cleanup
5262DROP TRIGGER trig_row_before ON rem1;
5263DROP TRIGGER trig_row_after ON rem1;
5264DROP TRIGGER trig_local_before ON loc1;
5265-- Test direct foreign table modification functionality
5266-- Test with statement-level triggers
5267CREATE TRIGGER trig_stmt_before
5268	BEFORE DELETE OR INSERT OR UPDATE ON rem1
5269	FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
5270EXPLAIN (verbose, costs off)
5271UPDATE rem1 set f2 = '';          -- can be pushed down
5272                        QUERY PLAN
5273----------------------------------------------------------
5274 Update on public.rem1
5275   ->  Foreign Update on public.rem1
5276         Remote SQL: UPDATE public.loc1 SET f2 = ''::text
5277(3 rows)
5278
5279EXPLAIN (verbose, costs off)
5280DELETE FROM rem1;                 -- can be pushed down
5281                 QUERY PLAN
5282---------------------------------------------
5283 Delete on public.rem1
5284   ->  Foreign Delete on public.rem1
5285         Remote SQL: DELETE FROM public.loc1
5286(3 rows)
5287
5288DROP TRIGGER trig_stmt_before ON rem1;
5289CREATE TRIGGER trig_stmt_after
5290	AFTER DELETE OR INSERT OR UPDATE ON rem1
5291	FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
5292EXPLAIN (verbose, costs off)
5293UPDATE rem1 set f2 = '';          -- can be pushed down
5294                        QUERY PLAN
5295----------------------------------------------------------
5296 Update on public.rem1
5297   ->  Foreign Update on public.rem1
5298         Remote SQL: UPDATE public.loc1 SET f2 = ''::text
5299(3 rows)
5300
5301EXPLAIN (verbose, costs off)
5302DELETE FROM rem1;                 -- can be pushed down
5303                 QUERY PLAN
5304---------------------------------------------
5305 Delete on public.rem1
5306   ->  Foreign Delete on public.rem1
5307         Remote SQL: DELETE FROM public.loc1
5308(3 rows)
5309
5310DROP TRIGGER trig_stmt_after ON rem1;
5311-- Test with row-level ON INSERT triggers
5312CREATE TRIGGER trig_row_before_insert
5313BEFORE INSERT ON rem1
5314FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
5315EXPLAIN (verbose, costs off)
5316UPDATE rem1 set f2 = '';          -- can be pushed down
5317                        QUERY PLAN
5318----------------------------------------------------------
5319 Update on public.rem1
5320   ->  Foreign Update on public.rem1
5321         Remote SQL: UPDATE public.loc1 SET f2 = ''::text
5322(3 rows)
5323
5324EXPLAIN (verbose, costs off)
5325DELETE FROM rem1;                 -- can be pushed down
5326                 QUERY PLAN
5327---------------------------------------------
5328 Delete on public.rem1
5329   ->  Foreign Delete on public.rem1
5330         Remote SQL: DELETE FROM public.loc1
5331(3 rows)
5332
5333DROP TRIGGER trig_row_before_insert ON rem1;
5334CREATE TRIGGER trig_row_after_insert
5335AFTER INSERT ON rem1
5336FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
5337EXPLAIN (verbose, costs off)
5338UPDATE rem1 set f2 = '';          -- can be pushed down
5339                        QUERY PLAN
5340----------------------------------------------------------
5341 Update on public.rem1
5342   ->  Foreign Update on public.rem1
5343         Remote SQL: UPDATE public.loc1 SET f2 = ''::text
5344(3 rows)
5345
5346EXPLAIN (verbose, costs off)
5347DELETE FROM rem1;                 -- can be pushed down
5348                 QUERY PLAN
5349---------------------------------------------
5350 Delete on public.rem1
5351   ->  Foreign Delete on public.rem1
5352         Remote SQL: DELETE FROM public.loc1
5353(3 rows)
5354
5355DROP TRIGGER trig_row_after_insert ON rem1;
5356-- Test with row-level ON UPDATE triggers
5357CREATE TRIGGER trig_row_before_update
5358BEFORE UPDATE ON rem1
5359FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
5360EXPLAIN (verbose, costs off)
5361UPDATE rem1 set f2 = '';          -- can't be pushed down
5362                              QUERY PLAN
5363-----------------------------------------------------------------------
5364 Update on public.rem1
5365   Remote SQL: UPDATE public.loc1 SET f1 = $2, f2 = $3 WHERE ctid = $1
5366   ->  Foreign Scan on public.rem1
5367         Output: f1, ''::text, ctid, rem1.*
5368         Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
5369(5 rows)
5370
5371EXPLAIN (verbose, costs off)
5372DELETE FROM rem1;                 -- can be pushed down
5373                 QUERY PLAN
5374---------------------------------------------
5375 Delete on public.rem1
5376   ->  Foreign Delete on public.rem1
5377         Remote SQL: DELETE FROM public.loc1
5378(3 rows)
5379
5380DROP TRIGGER trig_row_before_update ON rem1;
5381CREATE TRIGGER trig_row_after_update
5382AFTER UPDATE ON rem1
5383FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
5384EXPLAIN (verbose, costs off)
5385UPDATE rem1 set f2 = '';          -- can't be pushed down
5386                                  QUERY PLAN
5387-------------------------------------------------------------------------------
5388 Update on public.rem1
5389   Remote SQL: UPDATE public.loc1 SET f2 = $2 WHERE ctid = $1 RETURNING f1, f2
5390   ->  Foreign Scan on public.rem1
5391         Output: f1, ''::text, ctid, rem1.*
5392         Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
5393(5 rows)
5394
5395EXPLAIN (verbose, costs off)
5396DELETE FROM rem1;                 -- can be pushed down
5397                 QUERY PLAN
5398---------------------------------------------
5399 Delete on public.rem1
5400   ->  Foreign Delete on public.rem1
5401         Remote SQL: DELETE FROM public.loc1
5402(3 rows)
5403
5404DROP TRIGGER trig_row_after_update ON rem1;
5405-- Test with row-level ON DELETE triggers
5406CREATE TRIGGER trig_row_before_delete
5407BEFORE DELETE ON rem1
5408FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
5409EXPLAIN (verbose, costs off)
5410UPDATE rem1 set f2 = '';          -- can be pushed down
5411                        QUERY PLAN
5412----------------------------------------------------------
5413 Update on public.rem1
5414   ->  Foreign Update on public.rem1
5415         Remote SQL: UPDATE public.loc1 SET f2 = ''::text
5416(3 rows)
5417
5418EXPLAIN (verbose, costs off)
5419DELETE FROM rem1;                 -- can't be pushed down
5420                             QUERY PLAN
5421---------------------------------------------------------------------
5422 Delete on public.rem1
5423   Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1
5424   ->  Foreign Scan on public.rem1
5425         Output: ctid, rem1.*
5426         Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
5427(5 rows)
5428
5429DROP TRIGGER trig_row_before_delete ON rem1;
5430CREATE TRIGGER trig_row_after_delete
5431AFTER DELETE ON rem1
5432FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
5433EXPLAIN (verbose, costs off)
5434UPDATE rem1 set f2 = '';          -- can be pushed down
5435                        QUERY PLAN
5436----------------------------------------------------------
5437 Update on public.rem1
5438   ->  Foreign Update on public.rem1
5439         Remote SQL: UPDATE public.loc1 SET f2 = ''::text
5440(3 rows)
5441
5442EXPLAIN (verbose, costs off)
5443DELETE FROM rem1;                 -- can't be pushed down
5444                               QUERY PLAN
5445------------------------------------------------------------------------
5446 Delete on public.rem1
5447   Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1 RETURNING f1, f2
5448   ->  Foreign Scan on public.rem1
5449         Output: ctid, rem1.*
5450         Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
5451(5 rows)
5452
5453DROP TRIGGER trig_row_after_delete ON rem1;
5454-- ===================================================================
5455-- test inheritance features
5456-- ===================================================================
5457CREATE TABLE a (aa TEXT);
5458CREATE TABLE loct (aa TEXT, bb TEXT);
5459CREATE FOREIGN TABLE b (bb TEXT) INHERITS (a)
5460  SERVER loopback OPTIONS (table_name 'loct');
5461INSERT INTO a(aa) VALUES('aaa');
5462INSERT INTO a(aa) VALUES('aaaa');
5463INSERT INTO a(aa) VALUES('aaaaa');
5464INSERT INTO b(aa) VALUES('bbb');
5465INSERT INTO b(aa) VALUES('bbbb');
5466INSERT INTO b(aa) VALUES('bbbbb');
5467SELECT tableoid::regclass, * FROM a;
5468 tableoid |  aa
5469----------+-------
5470 a        | aaa
5471 a        | aaaa
5472 a        | aaaaa
5473 b        | bbb
5474 b        | bbbb
5475 b        | bbbbb
5476(6 rows)
5477
5478SELECT tableoid::regclass, * FROM b;
5479 tableoid |  aa   | bb
5480----------+-------+----
5481 b        | bbb   |
5482 b        | bbbb  |
5483 b        | bbbbb |
5484(3 rows)
5485
5486SELECT tableoid::regclass, * FROM ONLY a;
5487 tableoid |  aa
5488----------+-------
5489 a        | aaa
5490 a        | aaaa
5491 a        | aaaaa
5492(3 rows)
5493
5494UPDATE a SET aa = 'zzzzzz' WHERE aa LIKE 'aaaa%';
5495SELECT tableoid::regclass, * FROM a;
5496 tableoid |   aa
5497----------+--------
5498 a        | aaa
5499 a        | zzzzzz
5500 a        | zzzzzz
5501 b        | bbb
5502 b        | bbbb
5503 b        | bbbbb
5504(6 rows)
5505
5506SELECT tableoid::regclass, * FROM b;
5507 tableoid |  aa   | bb
5508----------+-------+----
5509 b        | bbb   |
5510 b        | bbbb  |
5511 b        | bbbbb |
5512(3 rows)
5513
5514SELECT tableoid::regclass, * FROM ONLY a;
5515 tableoid |   aa
5516----------+--------
5517 a        | aaa
5518 a        | zzzzzz
5519 a        | zzzzzz
5520(3 rows)
5521
5522UPDATE b SET aa = 'new';
5523SELECT tableoid::regclass, * FROM a;
5524 tableoid |   aa
5525----------+--------
5526 a        | aaa
5527 a        | zzzzzz
5528 a        | zzzzzz
5529 b        | new
5530 b        | new
5531 b        | new
5532(6 rows)
5533
5534SELECT tableoid::regclass, * FROM b;
5535 tableoid | aa  | bb
5536----------+-----+----
5537 b        | new |
5538 b        | new |
5539 b        | new |
5540(3 rows)
5541
5542SELECT tableoid::regclass, * FROM ONLY a;
5543 tableoid |   aa
5544----------+--------
5545 a        | aaa
5546 a        | zzzzzz
5547 a        | zzzzzz
5548(3 rows)
5549
5550UPDATE a SET aa = 'newtoo';
5551SELECT tableoid::regclass, * FROM a;
5552 tableoid |   aa
5553----------+--------
5554 a        | newtoo
5555 a        | newtoo
5556 a        | newtoo
5557 b        | newtoo
5558 b        | newtoo
5559 b        | newtoo
5560(6 rows)
5561
5562SELECT tableoid::regclass, * FROM b;
5563 tableoid |   aa   | bb
5564----------+--------+----
5565 b        | newtoo |
5566 b        | newtoo |
5567 b        | newtoo |
5568(3 rows)
5569
5570SELECT tableoid::regclass, * FROM ONLY a;
5571 tableoid |   aa
5572----------+--------
5573 a        | newtoo
5574 a        | newtoo
5575 a        | newtoo
5576(3 rows)
5577
5578DELETE FROM a;
5579SELECT tableoid::regclass, * FROM a;
5580 tableoid | aa
5581----------+----
5582(0 rows)
5583
5584SELECT tableoid::regclass, * FROM b;
5585 tableoid | aa | bb
5586----------+----+----
5587(0 rows)
5588
5589SELECT tableoid::regclass, * FROM ONLY a;
5590 tableoid | aa
5591----------+----
5592(0 rows)
5593
5594DROP TABLE a CASCADE;
5595NOTICE:  drop cascades to foreign table b
5596DROP TABLE loct;
5597-- Check SELECT FOR UPDATE/SHARE with an inherited source table
5598create table loct1 (f1 int, f2 int, f3 int);
5599create table loct2 (f1 int, f2 int, f3 int);
5600create table foo (f1 int, f2 int);
5601create foreign table foo2 (f3 int) inherits (foo)
5602  server loopback options (table_name 'loct1');
5603create table bar (f1 int, f2 int);
5604create foreign table bar2 (f3 int) inherits (bar)
5605  server loopback options (table_name 'loct2');
5606insert into foo values(1,1);
5607insert into foo values(3,3);
5608insert into foo2 values(2,2,2);
5609insert into foo2 values(4,4,4);
5610insert into bar values(1,11);
5611insert into bar values(2,22);
5612insert into bar values(6,66);
5613insert into bar2 values(3,33,33);
5614insert into bar2 values(4,44,44);
5615insert into bar2 values(7,77,77);
5616explain (verbose, costs off)
5617select * from bar where f1 in (select f1 from foo) for update;
5618                                          QUERY PLAN
5619----------------------------------------------------------------------------------------------
5620 LockRows
5621   Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
5622   ->  Hash Join
5623         Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
5624         Hash Cond: (bar.f1 = foo.f1)
5625         ->  Append
5626               ->  Seq Scan on public.bar
5627                     Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid
5628               ->  Foreign Scan on public.bar2
5629                     Output: bar2.f1, bar2.f2, bar2.ctid, bar2.*, bar2.tableoid
5630                     Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
5631         ->  Hash
5632               Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5633               ->  HashAggregate
5634                     Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5635                     Group Key: foo.f1
5636                     ->  Append
5637                           ->  Seq Scan on public.foo
5638                                 Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5639                           ->  Foreign Scan on public.foo2
5640                                 Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
5641                                 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
5642(22 rows)
5643
5644select * from bar where f1 in (select f1 from foo) for update;
5645 f1 | f2
5646----+----
5647  1 | 11
5648  2 | 22
5649  3 | 33
5650  4 | 44
5651(4 rows)
5652
5653explain (verbose, costs off)
5654select * from bar where f1 in (select f1 from foo) for share;
5655                                          QUERY PLAN
5656----------------------------------------------------------------------------------------------
5657 LockRows
5658   Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
5659   ->  Hash Join
5660         Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
5661         Hash Cond: (bar.f1 = foo.f1)
5662         ->  Append
5663               ->  Seq Scan on public.bar
5664                     Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid
5665               ->  Foreign Scan on public.bar2
5666                     Output: bar2.f1, bar2.f2, bar2.ctid, bar2.*, bar2.tableoid
5667                     Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
5668         ->  Hash
5669               Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5670               ->  HashAggregate
5671                     Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5672                     Group Key: foo.f1
5673                     ->  Append
5674                           ->  Seq Scan on public.foo
5675                                 Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5676                           ->  Foreign Scan on public.foo2
5677                                 Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
5678                                 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
5679(22 rows)
5680
5681select * from bar where f1 in (select f1 from foo) for share;
5682 f1 | f2
5683----+----
5684  1 | 11
5685  2 | 22
5686  3 | 33
5687  4 | 44
5688(4 rows)
5689
5690-- Check UPDATE with inherited target and an inherited source table
5691explain (verbose, costs off)
5692update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
5693                                         QUERY PLAN
5694---------------------------------------------------------------------------------------------
5695 Update on public.bar
5696   Update on public.bar
5697   Foreign Update on public.bar2
5698     Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
5699   ->  Hash Join
5700         Output: bar.f1, (bar.f2 + 100), bar.ctid, foo.ctid, foo.*, foo.tableoid
5701         Hash Cond: (bar.f1 = foo.f1)
5702         ->  Seq Scan on public.bar
5703               Output: bar.f1, bar.f2, bar.ctid
5704         ->  Hash
5705               Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5706               ->  HashAggregate
5707                     Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5708                     Group Key: foo.f1
5709                     ->  Append
5710                           ->  Seq Scan on public.foo
5711                                 Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5712                           ->  Foreign Scan on public.foo2
5713                                 Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
5714                                 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
5715   ->  Hash Join
5716         Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.ctid, foo.ctid, foo.*, foo.tableoid
5717         Hash Cond: (bar2.f1 = foo.f1)
5718         ->  Foreign Scan on public.bar2
5719               Output: bar2.f1, bar2.f2, bar2.f3, bar2.ctid
5720               Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
5721         ->  Hash
5722               Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5723               ->  HashAggregate
5724                     Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5725                     Group Key: foo.f1
5726                     ->  Append
5727                           ->  Seq Scan on public.foo
5728                                 Output: foo.ctid, foo.*, foo.tableoid, foo.f1
5729                           ->  Foreign Scan on public.foo2
5730                                 Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
5731                                 Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
5732(37 rows)
5733
5734update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
5735select tableoid::regclass, * from bar order by 1,2;
5736 tableoid | f1 | f2
5737----------+----+-----
5738 bar      |  1 | 111
5739 bar      |  2 | 122
5740 bar      |  6 |  66
5741 bar2     |  3 | 133
5742 bar2     |  4 | 144
5743 bar2     |  7 |  77
5744(6 rows)
5745
5746-- Check UPDATE with inherited target and an appendrel subquery
5747explain (verbose, costs off)
5748update bar set f2 = f2 + 100
5749from
5750  ( select f1 from foo union all select f1+3 from foo ) ss
5751where bar.f1 = ss.f1;
5752                                      QUERY PLAN
5753--------------------------------------------------------------------------------------
5754 Update on public.bar
5755   Update on public.bar
5756   Foreign Update on public.bar2
5757     Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
5758   ->  Hash Join
5759         Output: bar.f1, (bar.f2 + 100), bar.ctid, (ROW(foo.f1))
5760         Hash Cond: (foo.f1 = bar.f1)
5761         ->  Append
5762               ->  Seq Scan on public.foo
5763                     Output: ROW(foo.f1), foo.f1
5764               ->  Foreign Scan on public.foo2
5765                     Output: ROW(foo2.f1), foo2.f1
5766                     Remote SQL: SELECT f1 FROM public.loct1
5767               ->  Seq Scan on public.foo foo_1
5768                     Output: ROW((foo_1.f1 + 3)), (foo_1.f1 + 3)
5769               ->  Foreign Scan on public.foo2 foo2_1
5770                     Output: ROW((foo2_1.f1 + 3)), (foo2_1.f1 + 3)
5771                     Remote SQL: SELECT f1 FROM public.loct1
5772         ->  Hash
5773               Output: bar.f1, bar.f2, bar.ctid
5774               ->  Seq Scan on public.bar
5775                     Output: bar.f1, bar.f2, bar.ctid
5776   ->  Merge Join
5777         Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.ctid, (ROW(foo.f1))
5778         Merge Cond: (bar2.f1 = foo.f1)
5779         ->  Sort
5780               Output: bar2.f1, bar2.f2, bar2.f3, bar2.ctid
5781               Sort Key: bar2.f1
5782               ->  Foreign Scan on public.bar2
5783                     Output: bar2.f1, bar2.f2, bar2.f3, bar2.ctid
5784                     Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
5785         ->  Sort
5786               Output: (ROW(foo.f1)), foo.f1
5787               Sort Key: foo.f1
5788               ->  Append
5789                     ->  Seq Scan on public.foo
5790                           Output: ROW(foo.f1), foo.f1
5791                     ->  Foreign Scan on public.foo2
5792                           Output: ROW(foo2.f1), foo2.f1
5793                           Remote SQL: SELECT f1 FROM public.loct1
5794                     ->  Seq Scan on public.foo foo_1
5795                           Output: ROW((foo_1.f1 + 3)), (foo_1.f1 + 3)
5796                     ->  Foreign Scan on public.foo2 foo2_1
5797                           Output: ROW((foo2_1.f1 + 3)), (foo2_1.f1 + 3)
5798                           Remote SQL: SELECT f1 FROM public.loct1
5799(45 rows)
5800
5801update bar set f2 = f2 + 100
5802from
5803  ( select f1 from foo union all select f1+3 from foo ) ss
5804where bar.f1 = ss.f1;
5805select tableoid::regclass, * from bar order by 1,2;
5806 tableoid | f1 | f2
5807----------+----+-----
5808 bar      |  1 | 211
5809 bar      |  2 | 222
5810 bar      |  6 | 166
5811 bar2     |  3 | 233
5812 bar2     |  4 | 244
5813 bar2     |  7 | 177
5814(6 rows)
5815
5816-- Test forcing the remote server to produce sorted data for a merge join,
5817-- but the foreign table is an inheritance child.
5818truncate table loct1;
5819truncate table only foo;
5820\set num_rows_foo 2000
5821insert into loct1 select generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2);
5822insert into foo select generate_series(1, :num_rows_foo, 2), generate_series(1, :num_rows_foo, 2);
5823SET enable_hashjoin to false;
5824SET enable_nestloop to false;
5825alter foreign table foo2 options (use_remote_estimate 'true');
5826create index i_loct1_f1 on loct1(f1);
5827create index i_foo_f1 on foo(f1);
5828analyze foo;
5829analyze loct1;
5830-- inner join; expressions in the clauses appear in the equivalence class list
5831explain (verbose, costs off)
5832	select foo.f1, loct1.f1 from foo join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
5833                                            QUERY PLAN
5834--------------------------------------------------------------------------------------------------
5835 Limit
5836   Output: foo.f1, loct1.f1, foo.f2
5837   ->  Sort
5838         Output: foo.f1, loct1.f1, foo.f2
5839         Sort Key: foo.f2
5840         ->  Merge Join
5841               Output: foo.f1, loct1.f1, foo.f2
5842               Merge Cond: (foo.f1 = loct1.f1)
5843               ->  Merge Append
5844                     Sort Key: foo.f1
5845                     ->  Index Scan using i_foo_f1 on public.foo
5846                           Output: foo.f1, foo.f2
5847                     ->  Foreign Scan on public.foo2
5848                           Output: foo2.f1, foo2.f2
5849                           Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
5850               ->  Index Only Scan using i_loct1_f1 on public.loct1
5851                     Output: loct1.f1
5852(17 rows)
5853
5854select foo.f1, loct1.f1 from foo join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
5855 f1 | f1
5856----+----
5857 20 | 20
5858 22 | 22
5859 24 | 24
5860 26 | 26
5861 28 | 28
5862 30 | 30
5863 32 | 32
5864 34 | 34
5865 36 | 36
5866 38 | 38
5867(10 rows)
5868
5869-- outer join; expressions in the clauses do not appear in equivalence class
5870-- list but no output change as compared to the previous query
5871explain (verbose, costs off)
5872	select foo.f1, loct1.f1 from foo left join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
5873                                            QUERY PLAN
5874--------------------------------------------------------------------------------------------------
5875 Limit
5876   Output: foo.f1, loct1.f1, foo.f2
5877   ->  Sort
5878         Output: foo.f1, loct1.f1, foo.f2
5879         Sort Key: foo.f2
5880         ->  Merge Left Join
5881               Output: foo.f1, loct1.f1, foo.f2
5882               Merge Cond: (foo.f1 = loct1.f1)
5883               ->  Merge Append
5884                     Sort Key: foo.f1
5885                     ->  Index Scan using i_foo_f1 on public.foo
5886                           Output: foo.f1, foo.f2
5887                     ->  Foreign Scan on public.foo2
5888                           Output: foo2.f1, foo2.f2
5889                           Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
5890               ->  Index Only Scan using i_loct1_f1 on public.loct1
5891                     Output: loct1.f1
5892(17 rows)
5893
5894select foo.f1, loct1.f1 from foo left join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
5895 f1 | f1
5896----+----
5897 10 | 10
5898 11 |
5899 12 | 12
5900 13 |
5901 14 | 14
5902 15 |
5903 16 | 16
5904 17 |
5905 18 | 18
5906 19 |
5907(10 rows)
5908
5909RESET enable_hashjoin;
5910RESET enable_nestloop;
5911-- Test that WHERE CURRENT OF is not supported
5912begin;
5913declare c cursor for select * from bar where f1 = 7;
5914fetch from c;
5915 f1 | f2
5916----+-----
5917  7 | 177
5918(1 row)
5919
5920update bar set f2 = null where current of c;
5921ERROR:  WHERE CURRENT OF is not supported for this table type
5922rollback;
5923explain (verbose, costs off)
5924delete from foo where f1 < 5 returning *;
5925                                   QUERY PLAN
5926--------------------------------------------------------------------------------
5927 Delete on public.foo
5928   Output: foo.f1, foo.f2
5929   Delete on public.foo
5930   Foreign Delete on public.foo2
5931   ->  Index Scan using i_foo_f1 on public.foo
5932         Output: foo.ctid
5933         Index Cond: (foo.f1 < 5)
5934   ->  Foreign Delete on public.foo2
5935         Remote SQL: DELETE FROM public.loct1 WHERE ((f1 < 5)) RETURNING f1, f2
5936(9 rows)
5937
5938delete from foo where f1 < 5 returning *;
5939 f1 | f2
5940----+----
5941  1 |  1
5942  3 |  3
5943  0 |  0
5944  2 |  2
5945  4 |  4
5946(5 rows)
5947
5948explain (verbose, costs off)
5949update bar set f2 = f2 + 100 returning *;
5950                                  QUERY PLAN
5951------------------------------------------------------------------------------
5952 Update on public.bar
5953   Output: bar.f1, bar.f2
5954   Update on public.bar
5955   Foreign Update on public.bar2
5956   ->  Seq Scan on public.bar
5957         Output: bar.f1, (bar.f2 + 100), bar.ctid
5958   ->  Foreign Update on public.bar2
5959         Remote SQL: UPDATE public.loct2 SET f2 = (f2 + 100) RETURNING f1, f2
5960(8 rows)
5961
5962update bar set f2 = f2 + 100 returning *;
5963 f1 | f2
5964----+-----
5965  1 | 311
5966  2 | 322
5967  6 | 266
5968  3 | 333
5969  4 | 344
5970  7 | 277
5971(6 rows)
5972
5973-- Test that UPDATE/DELETE with inherited target works with row-level triggers
5974CREATE TRIGGER trig_row_before
5975BEFORE UPDATE OR DELETE ON bar2
5976FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
5977CREATE TRIGGER trig_row_after
5978AFTER UPDATE OR DELETE ON bar2
5979FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
5980explain (verbose, costs off)
5981update bar set f2 = f2 + 100;
5982                                               QUERY PLAN
5983--------------------------------------------------------------------------------------------------------
5984 Update on public.bar
5985   Update on public.bar
5986   Foreign Update on public.bar2
5987     Remote SQL: UPDATE public.loct2 SET f1 = $2, f2 = $3, f3 = $4 WHERE ctid = $1 RETURNING f1, f2, f3
5988   ->  Seq Scan on public.bar
5989         Output: bar.f1, (bar.f2 + 100), bar.ctid
5990   ->  Foreign Scan on public.bar2
5991         Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.ctid, bar2.*
5992         Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
5993(9 rows)
5994
5995update bar set f2 = f2 + 100;
5996NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
5997NOTICE:  OLD: (3,333,33),NEW: (3,433,33)
5998NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
5999NOTICE:  OLD: (4,344,44),NEW: (4,444,44)
6000NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
6001NOTICE:  OLD: (7,277,77),NEW: (7,377,77)
6002NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
6003NOTICE:  OLD: (3,333,33),NEW: (3,433,33)
6004NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
6005NOTICE:  OLD: (4,344,44),NEW: (4,444,44)
6006NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
6007NOTICE:  OLD: (7,277,77),NEW: (7,377,77)
6008explain (verbose, costs off)
6009delete from bar where f2 < 400;
6010                                         QUERY PLAN
6011---------------------------------------------------------------------------------------------
6012 Delete on public.bar
6013   Delete on public.bar
6014   Foreign Delete on public.bar2
6015     Remote SQL: DELETE FROM public.loct2 WHERE ctid = $1 RETURNING f1, f2, f3
6016   ->  Seq Scan on public.bar
6017         Output: bar.ctid
6018         Filter: (bar.f2 < 400)
6019   ->  Foreign Scan on public.bar2
6020         Output: bar2.ctid, bar2.*
6021         Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 WHERE ((f2 < 400)) FOR UPDATE
6022(10 rows)
6023
6024delete from bar where f2 < 400;
6025NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON bar2
6026NOTICE:  OLD: (7,377,77)
6027NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON bar2
6028NOTICE:  OLD: (7,377,77)
6029-- cleanup
6030drop table foo cascade;
6031NOTICE:  drop cascades to foreign table foo2
6032drop table bar cascade;
6033NOTICE:  drop cascades to foreign table bar2
6034drop table loct1;
6035drop table loct2;
6036-- ===================================================================
6037-- test IMPORT FOREIGN SCHEMA
6038-- ===================================================================
6039CREATE SCHEMA import_source;
6040CREATE TABLE import_source.t1 (c1 int, c2 varchar NOT NULL);
6041CREATE TABLE import_source.t2 (c1 int default 42, c2 varchar NULL, c3 text collate "POSIX");
6042CREATE TYPE typ1 AS (m1 int, m2 varchar);
6043CREATE TABLE import_source.t3 (c1 timestamptz default now(), c2 typ1);
6044CREATE TABLE import_source."x 4" (c1 float8, "C 2" text, c3 varchar(42));
6045CREATE TABLE import_source."x 5" (c1 float8);
6046ALTER TABLE import_source."x 5" DROP COLUMN c1;
6047CREATE SCHEMA import_dest1;
6048IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest1;
6049\det+ import_dest1.*
6050                                     List of foreign tables
6051    Schema    | Table |  Server  |                   FDW Options                   | Description
6052--------------+-------+----------+-------------------------------------------------+-------------
6053 import_dest1 | t1    | loopback | (schema_name 'import_source', table_name 't1')  |
6054 import_dest1 | t2    | loopback | (schema_name 'import_source', table_name 't2')  |
6055 import_dest1 | t3    | loopback | (schema_name 'import_source', table_name 't3')  |
6056 import_dest1 | x 4   | loopback | (schema_name 'import_source', table_name 'x 4') |
6057 import_dest1 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') |
6058(5 rows)
6059
6060\d import_dest1.*
6061               Foreign table "import_dest1.t1"
6062 Column |       Type        | Modifiers |    FDW Options
6063--------+-------------------+-----------+--------------------
6064 c1     | integer           |           | (column_name 'c1')
6065 c2     | character varying | not null  | (column_name 'c2')
6066Server: loopback
6067FDW Options: (schema_name 'import_source', table_name 't1')
6068
6069                 Foreign table "import_dest1.t2"
6070 Column |       Type        |   Modifiers   |    FDW Options
6071--------+-------------------+---------------+--------------------
6072 c1     | integer           |               | (column_name 'c1')
6073 c2     | character varying |               | (column_name 'c2')
6074 c3     | text              | collate POSIX | (column_name 'c3')
6075Server: loopback
6076FDW Options: (schema_name 'import_source', table_name 't2')
6077
6078                  Foreign table "import_dest1.t3"
6079 Column |           Type           | Modifiers |    FDW Options
6080--------+--------------------------+-----------+--------------------
6081 c1     | timestamp with time zone |           | (column_name 'c1')
6082 c2     | typ1                     |           | (column_name 'c2')
6083Server: loopback
6084FDW Options: (schema_name 'import_source', table_name 't3')
6085
6086                 Foreign table "import_dest1.x 4"
6087 Column |         Type          | Modifiers |     FDW Options
6088--------+-----------------------+-----------+---------------------
6089 c1     | double precision      |           | (column_name 'c1')
6090 C 2    | text                  |           | (column_name 'C 2')
6091 c3     | character varying(42) |           | (column_name 'c3')
6092Server: loopback
6093FDW Options: (schema_name 'import_source', table_name 'x 4')
6094
6095    Foreign table "import_dest1.x 5"
6096 Column | Type | Modifiers | FDW Options
6097--------+------+-----------+-------------
6098Server: loopback
6099FDW Options: (schema_name 'import_source', table_name 'x 5')
6100
6101-- Options
6102CREATE SCHEMA import_dest2;
6103IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest2
6104  OPTIONS (import_default 'true');
6105\det+ import_dest2.*
6106                                     List of foreign tables
6107    Schema    | Table |  Server  |                   FDW Options                   | Description
6108--------------+-------+----------+-------------------------------------------------+-------------
6109 import_dest2 | t1    | loopback | (schema_name 'import_source', table_name 't1')  |
6110 import_dest2 | t2    | loopback | (schema_name 'import_source', table_name 't2')  |
6111 import_dest2 | t3    | loopback | (schema_name 'import_source', table_name 't3')  |
6112 import_dest2 | x 4   | loopback | (schema_name 'import_source', table_name 'x 4') |
6113 import_dest2 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') |
6114(5 rows)
6115
6116\d import_dest2.*
6117               Foreign table "import_dest2.t1"
6118 Column |       Type        | Modifiers |    FDW Options
6119--------+-------------------+-----------+--------------------
6120 c1     | integer           |           | (column_name 'c1')
6121 c2     | character varying | not null  | (column_name 'c2')
6122Server: loopback
6123FDW Options: (schema_name 'import_source', table_name 't1')
6124
6125                 Foreign table "import_dest2.t2"
6126 Column |       Type        |   Modifiers   |    FDW Options
6127--------+-------------------+---------------+--------------------
6128 c1     | integer           | default 42    | (column_name 'c1')
6129 c2     | character varying |               | (column_name 'c2')
6130 c3     | text              | collate POSIX | (column_name 'c3')
6131Server: loopback
6132FDW Options: (schema_name 'import_source', table_name 't2')
6133
6134                    Foreign table "import_dest2.t3"
6135 Column |           Type           |   Modifiers   |    FDW Options
6136--------+--------------------------+---------------+--------------------
6137 c1     | timestamp with time zone | default now() | (column_name 'c1')
6138 c2     | typ1                     |               | (column_name 'c2')
6139Server: loopback
6140FDW Options: (schema_name 'import_source', table_name 't3')
6141
6142                 Foreign table "import_dest2.x 4"
6143 Column |         Type          | Modifiers |     FDW Options
6144--------+-----------------------+-----------+---------------------
6145 c1     | double precision      |           | (column_name 'c1')
6146 C 2    | text                  |           | (column_name 'C 2')
6147 c3     | character varying(42) |           | (column_name 'c3')
6148Server: loopback
6149FDW Options: (schema_name 'import_source', table_name 'x 4')
6150
6151    Foreign table "import_dest2.x 5"
6152 Column | Type | Modifiers | FDW Options
6153--------+------+-----------+-------------
6154Server: loopback
6155FDW Options: (schema_name 'import_source', table_name 'x 5')
6156
6157CREATE SCHEMA import_dest3;
6158IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest3
6159  OPTIONS (import_collate 'false', import_not_null 'false');
6160\det+ import_dest3.*
6161                                     List of foreign tables
6162    Schema    | Table |  Server  |                   FDW Options                   | Description
6163--------------+-------+----------+-------------------------------------------------+-------------
6164 import_dest3 | t1    | loopback | (schema_name 'import_source', table_name 't1')  |
6165 import_dest3 | t2    | loopback | (schema_name 'import_source', table_name 't2')  |
6166 import_dest3 | t3    | loopback | (schema_name 'import_source', table_name 't3')  |
6167 import_dest3 | x 4   | loopback | (schema_name 'import_source', table_name 'x 4') |
6168 import_dest3 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') |
6169(5 rows)
6170
6171\d import_dest3.*
6172               Foreign table "import_dest3.t1"
6173 Column |       Type        | Modifiers |    FDW Options
6174--------+-------------------+-----------+--------------------
6175 c1     | integer           |           | (column_name 'c1')
6176 c2     | character varying |           | (column_name 'c2')
6177Server: loopback
6178FDW Options: (schema_name 'import_source', table_name 't1')
6179
6180               Foreign table "import_dest3.t2"
6181 Column |       Type        | Modifiers |    FDW Options
6182--------+-------------------+-----------+--------------------
6183 c1     | integer           |           | (column_name 'c1')
6184 c2     | character varying |           | (column_name 'c2')
6185 c3     | text              |           | (column_name 'c3')
6186Server: loopback
6187FDW Options: (schema_name 'import_source', table_name 't2')
6188
6189                  Foreign table "import_dest3.t3"
6190 Column |           Type           | Modifiers |    FDW Options
6191--------+--------------------------+-----------+--------------------
6192 c1     | timestamp with time zone |           | (column_name 'c1')
6193 c2     | typ1                     |           | (column_name 'c2')
6194Server: loopback
6195FDW Options: (schema_name 'import_source', table_name 't3')
6196
6197                 Foreign table "import_dest3.x 4"
6198 Column |         Type          | Modifiers |     FDW Options
6199--------+-----------------------+-----------+---------------------
6200 c1     | double precision      |           | (column_name 'c1')
6201 C 2    | text                  |           | (column_name 'C 2')
6202 c3     | character varying(42) |           | (column_name 'c3')
6203Server: loopback
6204FDW Options: (schema_name 'import_source', table_name 'x 4')
6205
6206    Foreign table "import_dest3.x 5"
6207 Column | Type | Modifiers | FDW Options
6208--------+------+-----------+-------------
6209Server: loopback
6210FDW Options: (schema_name 'import_source', table_name 'x 5')
6211
6212-- Check LIMIT TO and EXCEPT
6213CREATE SCHEMA import_dest4;
6214IMPORT FOREIGN SCHEMA import_source LIMIT TO (t1, nonesuch)
6215  FROM SERVER loopback INTO import_dest4;
6216\det+ import_dest4.*
6217                                     List of foreign tables
6218    Schema    | Table |  Server  |                  FDW Options                   | Description
6219--------------+-------+----------+------------------------------------------------+-------------
6220 import_dest4 | t1    | loopback | (schema_name 'import_source', table_name 't1') |
6221(1 row)
6222
6223IMPORT FOREIGN SCHEMA import_source EXCEPT (t1, "x 4", nonesuch)
6224  FROM SERVER loopback INTO import_dest4;
6225\det+ import_dest4.*
6226                                     List of foreign tables
6227    Schema    | Table |  Server  |                   FDW Options                   | Description
6228--------------+-------+----------+-------------------------------------------------+-------------
6229 import_dest4 | t1    | loopback | (schema_name 'import_source', table_name 't1')  |
6230 import_dest4 | t2    | loopback | (schema_name 'import_source', table_name 't2')  |
6231 import_dest4 | t3    | loopback | (schema_name 'import_source', table_name 't3')  |
6232 import_dest4 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') |
6233(4 rows)
6234
6235-- Assorted error cases
6236IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest4;
6237ERROR:  relation "t1" already exists
6238CONTEXT:  importing foreign table "t1"
6239IMPORT FOREIGN SCHEMA nonesuch FROM SERVER loopback INTO import_dest4;
6240ERROR:  schema "nonesuch" is not present on foreign server "loopback"
6241IMPORT FOREIGN SCHEMA nonesuch FROM SERVER loopback INTO notthere;
6242ERROR:  schema "notthere" does not exist
6243IMPORT FOREIGN SCHEMA nonesuch FROM SERVER nowhere INTO notthere;
6244ERROR:  server "nowhere" does not exist
6245-- Check case of a type present only on the remote server.
6246-- We can fake this by dropping the type locally in our transaction.
6247CREATE TYPE "Colors" AS ENUM ('red', 'green', 'blue');
6248CREATE TABLE import_source.t5 (c1 int, c2 text collate "C", "Col" "Colors");
6249CREATE SCHEMA import_dest5;
6250BEGIN;
6251DROP TYPE "Colors" CASCADE;
6252NOTICE:  drop cascades to table import_source.t5 column Col
6253IMPORT FOREIGN SCHEMA import_source LIMIT TO (t5)
6254  FROM SERVER loopback INTO import_dest5;  -- ERROR
6255ERROR:  type "public.Colors" does not exist
6256LINE 4:   "Col" public."Colors" OPTIONS (column_name 'Col')
6257                ^
6258QUERY:  CREATE FOREIGN TABLE t5 (
6259  c1 integer OPTIONS (column_name 'c1'),
6260  c2 text OPTIONS (column_name 'c2') COLLATE pg_catalog."C",
6261  "Col" public."Colors" OPTIONS (column_name 'Col')
6262) SERVER loopback
6263OPTIONS (schema_name 'import_source', table_name 't5');
6264CONTEXT:  importing foreign table "t5"
6265ROLLBACK;
6266BEGIN;
6267CREATE SERVER fetch101 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( fetch_size '101' );
6268SELECT count(*)
6269FROM pg_foreign_server
6270WHERE srvname = 'fetch101'
6271AND srvoptions @> array['fetch_size=101'];
6272 count
6273-------
6274     1
6275(1 row)
6276
6277ALTER SERVER fetch101 OPTIONS( SET fetch_size '202' );
6278SELECT count(*)
6279FROM pg_foreign_server
6280WHERE srvname = 'fetch101'
6281AND srvoptions @> array['fetch_size=101'];
6282 count
6283-------
6284     0
6285(1 row)
6286
6287SELECT count(*)
6288FROM pg_foreign_server
6289WHERE srvname = 'fetch101'
6290AND srvoptions @> array['fetch_size=202'];
6291 count
6292-------
6293     1
6294(1 row)
6295
6296CREATE FOREIGN TABLE table30000 ( x int ) SERVER fetch101 OPTIONS ( fetch_size '30000' );
6297SELECT COUNT(*)
6298FROM pg_foreign_table
6299WHERE ftrelid = 'table30000'::regclass
6300AND ftoptions @> array['fetch_size=30000'];
6301 count
6302-------
6303     1
6304(1 row)
6305
6306ALTER FOREIGN TABLE table30000 OPTIONS ( SET fetch_size '60000');
6307SELECT COUNT(*)
6308FROM pg_foreign_table
6309WHERE ftrelid = 'table30000'::regclass
6310AND ftoptions @> array['fetch_size=30000'];
6311 count
6312-------
6313     0
6314(1 row)
6315
6316SELECT COUNT(*)
6317FROM pg_foreign_table
6318WHERE ftrelid = 'table30000'::regclass
6319AND ftoptions @> array['fetch_size=60000'];
6320 count
6321-------
6322     1
6323(1 row)
6324
6325ROLLBACK;
6326-- ===================================================================
6327-- test connection invalidation cases
6328-- ===================================================================
6329-- This test case is for closing the connection in pgfdw_xact_callback
6330BEGIN;
6331-- Connection xact depth becomes 1 i.e. the connection is in midst of the xact.
6332SELECT 1 FROM ft1 LIMIT 1;
6333 ?column?
6334----------
6335        1
6336(1 row)
6337
6338-- Connection is not closed at the end of the alter statement in
6339-- pgfdw_inval_callback. That's because the connection is in midst of this
6340-- xact, it is just marked as invalid.
6341ALTER SERVER loopback OPTIONS (ADD use_remote_estimate 'off');
6342-- The invalid connection gets closed in pgfdw_xact_callback during commit.
6343COMMIT;
6344