]> granicus.if.org Git - postgresql/blob - contrib/postgres_fdw/expected/postgres_fdw.out
postgres_fdw: Remove CTID output from some tests.
[postgresql] / contrib / postgres_fdw / expected / postgres_fdw.out
1 -- ===================================================================
2 -- create FDW objects
3 -- ===================================================================
4 CREATE EXTENSION postgres_fdw;
5 CREATE SERVER testserver1 FOREIGN DATA WRAPPER postgres_fdw;
6 DO $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$;
18 CREATE USER MAPPING FOR public SERVER testserver1
19         OPTIONS (user 'value', password 'value');
20 CREATE USER MAPPING FOR CURRENT_USER SERVER loopback;
21 CREATE USER MAPPING FOR CURRENT_USER SERVER loopback2;
22 -- ===================================================================
23 -- create objects used through FDW loopback server
24 -- ===================================================================
25 CREATE TYPE user_enum AS ENUM ('foo', 'bar', 'buz');
26 CREATE SCHEMA "S 1";
27 CREATE 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 );
38 CREATE TABLE "S 1"."T 2" (
39         c1 int NOT NULL,
40         c2 text,
41         CONSTRAINT t2_pkey PRIMARY KEY (c1)
42 );
43 CREATE 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 );
49 CREATE 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 );
55 INSERT 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;
65 INSERT INTO "S 1"."T 2"
66         SELECT id,
67                'AAA' || to_char(id, 'FM000')
68         FROM generate_series(1, 100) id;
69 INSERT INTO "S 1"."T 3"
70         SELECT id,
71                id + 1,
72                'AAA' || to_char(id, 'FM000')
73         FROM generate_series(1, 100) id;
74 DELETE FROM "S 1"."T 3" WHERE c1 % 2 != 0;      -- delete for outer join tests
75 INSERT INTO "S 1"."T 4"
76         SELECT id,
77                id + 1,
78                'AAA' || to_char(id, 'FM000')
79         FROM generate_series(1, 100) id;
80 DELETE FROM "S 1"."T 4" WHERE c1 % 3 != 0;      -- delete for outer join tests
81 ANALYZE "S 1"."T 1";
82 ANALYZE "S 1"."T 2";
83 ANALYZE "S 1"."T 3";
84 ANALYZE "S 1"."T 4";
85 -- ===================================================================
86 -- create foreign tables
87 -- ===================================================================
88 CREATE 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;
99 ALTER FOREIGN TABLE ft1 DROP COLUMN c0;
100 CREATE 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;
111 ALTER FOREIGN TABLE ft2 DROP COLUMN cx;
112 CREATE 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');
117 CREATE 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');
122 CREATE 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 -- A table with oids. CREATE FOREIGN TABLE doesn't support the
128 -- WITH OIDS option, but ALTER does.
129 CREATE FOREIGN TABLE ft_pg_type (
130         typname name,
131         typlen smallint
132 ) SERVER loopback OPTIONS (schema_name 'pg_catalog', table_name 'pg_type');
133 ALTER TABLE ft_pg_type SET WITH OIDS;
134 -- ===================================================================
135 -- tests for validator
136 -- ===================================================================
137 -- requiressl, krbsrvname and gsslib are omitted because they depend on
138 -- configure options
139 ALTER SERVER testserver1 OPTIONS (
140         use_remote_estimate 'false',
141         updatable 'true',
142         fdw_startup_cost '123.456',
143         fdw_tuple_cost '0.123',
144         service 'value',
145         connect_timeout 'value',
146         dbname 'value',
147         host 'value',
148         hostaddr 'value',
149         port 'value',
150         --client_encoding 'value',
151         application_name 'value',
152         --fallback_application_name 'value',
153         keepalives 'value',
154         keepalives_idle 'value',
155         keepalives_interval 'value',
156         -- requiressl 'value',
157         sslcompression 'value',
158         sslmode 'value',
159         sslcert 'value',
160         sslkey 'value',
161         sslrootcert 'value',
162         sslcrl 'value'
163         --requirepeer 'value',
164         -- krbsrvname 'value',
165         -- gsslib 'value',
166         --replication 'value'
167 );
168 -- Error, invalid list syntax
169 ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo; bar');
170 ERROR:  parameter "extensions" must be a list of extension names
171 -- OK but gets a warning
172 ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo, bar');
173 WARNING:  extension "foo" is not installed
174 WARNING:  extension "bar" is not installed
175 ALTER SERVER testserver1 OPTIONS (DROP extensions);
176 ALTER USER MAPPING FOR public SERVER testserver1
177         OPTIONS (DROP user, DROP password);
178 ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name 'T 1');
179 ALTER FOREIGN TABLE ft2 OPTIONS (schema_name 'S 1', table_name 'T 1');
180 ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
181 ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
182 \det+
183                                       List of foreign tables
184  Schema |   Table    |  Server   |                   FDW options                    | Description 
185 --------+------------+-----------+--------------------------------------------------+-------------
186  public | ft1        | loopback  | (schema_name 'S 1', table_name 'T 1')            | 
187  public | ft2        | loopback  | (schema_name 'S 1', table_name 'T 1')            | 
188  public | ft4        | loopback  | (schema_name 'S 1', table_name 'T 3')            | 
189  public | ft5        | loopback  | (schema_name 'S 1', table_name 'T 4')            | 
190  public | ft6        | loopback2 | (schema_name 'S 1', table_name 'T 4')            | 
191  public | ft_pg_type | loopback  | (schema_name 'pg_catalog', table_name 'pg_type') | 
192 (6 rows)
193
194 -- Test that alteration of server options causes reconnection
195 -- Remote's errors might be non-English, so hide them to ensure stable results
196 \set VERBOSITY terse
197 SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1;  -- should work
198   c3   |              c4              
199 -------+------------------------------
200  00001 | Fri Jan 02 00:00:00 1970 PST
201 (1 row)
202
203 ALTER SERVER loopback OPTIONS (SET dbname 'no such database');
204 SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1;  -- should fail
205 ERROR:  could not connect to server "loopback"
206 DO $d$
207     BEGIN
208         EXECUTE $$ALTER SERVER loopback
209             OPTIONS (SET dbname '$$||current_database()||$$')$$;
210     END;
211 $d$;
212 SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1;  -- should work again
213   c3   |              c4              
214 -------+------------------------------
215  00001 | Fri Jan 02 00:00:00 1970 PST
216 (1 row)
217
218 -- Test that alteration of user mapping options causes reconnection
219 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback
220   OPTIONS (ADD user 'no such user');
221 SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1;  -- should fail
222 ERROR:  could not connect to server "loopback"
223 ALTER USER MAPPING FOR CURRENT_USER SERVER loopback
224   OPTIONS (DROP user);
225 SELECT c3, c4 FROM ft1 ORDER BY c3, c1 LIMIT 1;  -- should work again
226   c3   |              c4              
227 -------+------------------------------
228  00001 | Fri Jan 02 00:00:00 1970 PST
229 (1 row)
230
231 \set VERBOSITY default
232 -- Now we should be able to run ANALYZE.
233 -- To exercise multiple code paths, we use local stats on ft1
234 -- and remote-estimate mode on ft2.
235 ANALYZE ft1;
236 ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true');
237 -- ===================================================================
238 -- simple queries
239 -- ===================================================================
240 -- single table without alias
241 EXPLAIN (COSTS OFF) SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
242         QUERY PLAN         
243 ---------------------------
244  Limit
245    ->  Foreign Scan on ft1
246 (2 rows)
247
248 SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
249  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
250 -----+----+-------+------------------------------+--------------------------+----+------------+-----
251  101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
252  102 |  2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
253  103 |  3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
254  104 |  4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
255  105 |  5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
256  106 |  6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
257  107 |  7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
258  108 |  8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
259  109 |  9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
260  110 |  0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0  | 0          | foo
261 (10 rows)
262
263 -- single table with alias - also test that tableoid sort is not pushed to remote side
264 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
265                                      QUERY PLAN                                      
266 -------------------------------------------------------------------------------------
267  Limit
268    Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
269    ->  Sort
270          Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
271          Sort Key: t1.c3, t1.c1, t1.tableoid
272          ->  Foreign Scan on public.ft1 t1
273                Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
274                Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
275 (8 rows)
276
277 SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
278  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
279 -----+----+-------+------------------------------+--------------------------+----+------------+-----
280  101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
281  102 |  2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
282  103 |  3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
283  104 |  4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
284  105 |  5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
285  106 |  6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
286  107 |  7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
287  108 |  8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
288  109 |  9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
289  110 |  0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0  | 0          | foo
290 (10 rows)
291
292 -- whole-row reference
293 EXPLAIN (VERBOSE, COSTS OFF) SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
294                                                            QUERY PLAN                                                           
295 --------------------------------------------------------------------------------------------------------------------------------
296  Limit
297    Output: t1.*, c3, c1
298    ->  Foreign Scan on public.ft1 t1
299          Output: t1.*, c3, c1
300          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
301 (5 rows)
302
303 SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
304                                              t1                                             
305 --------------------------------------------------------------------------------------------
306  (101,1,00101,"Fri Jan 02 00:00:00 1970 PST","Fri Jan 02 00:00:00 1970",1,"1         ",foo)
307  (102,2,00102,"Sat Jan 03 00:00:00 1970 PST","Sat Jan 03 00:00:00 1970",2,"2         ",foo)
308  (103,3,00103,"Sun Jan 04 00:00:00 1970 PST","Sun Jan 04 00:00:00 1970",3,"3         ",foo)
309  (104,4,00104,"Mon Jan 05 00:00:00 1970 PST","Mon Jan 05 00:00:00 1970",4,"4         ",foo)
310  (105,5,00105,"Tue Jan 06 00:00:00 1970 PST","Tue Jan 06 00:00:00 1970",5,"5         ",foo)
311  (106,6,00106,"Wed Jan 07 00:00:00 1970 PST","Wed Jan 07 00:00:00 1970",6,"6         ",foo)
312  (107,7,00107,"Thu Jan 08 00:00:00 1970 PST","Thu Jan 08 00:00:00 1970",7,"7         ",foo)
313  (108,8,00108,"Fri Jan 09 00:00:00 1970 PST","Fri Jan 09 00:00:00 1970",8,"8         ",foo)
314  (109,9,00109,"Sat Jan 10 00:00:00 1970 PST","Sat Jan 10 00:00:00 1970",9,"9         ",foo)
315  (110,0,00110,"Sun Jan 11 00:00:00 1970 PST","Sun Jan 11 00:00:00 1970",0,"0         ",foo)
316 (10 rows)
317
318 -- empty result
319 SELECT * FROM ft1 WHERE false;
320  c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 
321 ----+----+----+----+----+----+----+----
322 (0 rows)
323
324 -- with WHERE clause
325 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1';
326                                                                    QUERY PLAN                                                                   
327 ------------------------------------------------------------------------------------------------------------------------------------------------
328  Foreign Scan on public.ft1 t1
329    Output: c1, c2, c3, c4, c5, c6, c7, c8
330    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))
331 (3 rows)
332
333 SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1';
334  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
335 -----+----+-------+------------------------------+--------------------------+----+------------+-----
336  101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
337 (1 row)
338
339 -- with FOR UPDATE/SHARE
340 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE;
341                                                    QUERY PLAN                                                   
342 ----------------------------------------------------------------------------------------------------------------
343  LockRows
344    Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
345    ->  Foreign Scan on public.ft1 t1
346          Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
347          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 101)) FOR UPDATE
348 (5 rows)
349
350 SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE;
351  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
352 -----+----+-------+------------------------------+--------------------------+----+------------+-----
353  101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
354 (1 row)
355
356 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE;
357                                                   QUERY PLAN                                                   
358 ---------------------------------------------------------------------------------------------------------------
359  LockRows
360    Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
361    ->  Foreign Scan on public.ft1 t1
362          Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
363          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 102)) FOR SHARE
364 (5 rows)
365
366 SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE;
367  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
368 -----+----+-------+------------------------------+--------------------------+----+------------+-----
369  102 |  2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
370 (1 row)
371
372 -- aggregate
373 SELECT COUNT(*) FROM ft1 t1;
374  count 
375 -------
376   1000
377 (1 row)
378
379 -- subquery
380 SELECT * FROM ft1 t1 WHERE t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 <= 10) ORDER BY c1;
381  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
382 ----+----+-------+------------------------------+--------------------------+----+------------+-----
383   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
384   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
385   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
386   4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
387   5 |  5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
388   6 |  6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
389   7 |  7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
390   8 |  8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
391   9 |  9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
392  10 |  0 | 00010 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0  | 0          | foo
393 (10 rows)
394
395 -- subquery+MAX
396 SELECT * FROM ft1 t1 WHERE t1.c3 = (SELECT MAX(c3) FROM ft2 t2) ORDER BY c1;
397   c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
398 ------+----+-------+------------------------------+--------------------------+----+------------+-----
399  1000 |  0 | 01000 | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0  | 0          | foo
400 (1 row)
401
402 -- used in CTE
403 WITH t1 AS (SELECT * FROM ft1 WHERE c1 <= 10) SELECT t2.c1, t2.c2, t2.c3, t2.c4 FROM t1, ft2 t2 WHERE t1.c1 = t2.c1 ORDER BY t1.c1;
404  c1 | c2 |  c3   |              c4              
405 ----+----+-------+------------------------------
406   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST
407   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST
408   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST
409   4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST
410   5 |  5 | 00005 | Tue Jan 06 00:00:00 1970 PST
411   6 |  6 | 00006 | Wed Jan 07 00:00:00 1970 PST
412   7 |  7 | 00007 | Thu Jan 08 00:00:00 1970 PST
413   8 |  8 | 00008 | Fri Jan 09 00:00:00 1970 PST
414   9 |  9 | 00009 | Sat Jan 10 00:00:00 1970 PST
415  10 |  0 | 00010 | Sun Jan 11 00:00:00 1970 PST
416 (10 rows)
417
418 -- fixed values
419 SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1;
420  ?column? | ?column? 
421 ----------+----------
422  fixed    | 
423 (1 row)
424
425 -- Test forcing the remote server to produce sorted data for a merge join.
426 SET enable_hashjoin TO false;
427 SET enable_nestloop TO false;
428 -- inner join; expressions in the clauses appear in the equivalence class list
429 EXPLAIN (VERBOSE, COSTS OFF)
430         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;
431                                       QUERY PLAN                                       
432 ---------------------------------------------------------------------------------------
433  Limit
434    Output: t1.c1, t2."C 1"
435    ->  Merge Join
436          Output: t1.c1, t2."C 1"
437          Inner Unique: true
438          Merge Cond: (t1.c1 = t2."C 1")
439          ->  Foreign Scan on public.ft2 t1
440                Output: t1.c1
441                Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
442          ->  Index Only Scan using t1_pkey on "S 1"."T 1" t2
443                Output: t2."C 1"
444 (11 rows)
445
446 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;
447  c1  | C 1 
448 -----+-----
449  101 | 101
450  102 | 102
451  103 | 103
452  104 | 104
453  105 | 105
454  106 | 106
455  107 | 107
456  108 | 108
457  109 | 109
458  110 | 110
459 (10 rows)
460
461 -- outer join; expressions in the clauses do not appear in equivalence class
462 -- list but no output change as compared to the previous query
463 EXPLAIN (VERBOSE, COSTS OFF)
464         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;
465                                       QUERY PLAN                                       
466 ---------------------------------------------------------------------------------------
467  Limit
468    Output: t1.c1, t2."C 1"
469    ->  Merge Left Join
470          Output: t1.c1, t2."C 1"
471          Inner Unique: true
472          Merge Cond: (t1.c1 = t2."C 1")
473          ->  Foreign Scan on public.ft2 t1
474                Output: t1.c1
475                Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
476          ->  Index Only Scan using t1_pkey on "S 1"."T 1" t2
477                Output: t2."C 1"
478 (11 rows)
479
480 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;
481  c1  | C 1 
482 -----+-----
483  101 | 101
484  102 | 102
485  103 | 103
486  104 | 104
487  105 | 105
488  106 | 106
489  107 | 107
490  108 | 108
491  109 | 109
492  110 | 110
493 (10 rows)
494
495 -- A join between local table and foreign join. ORDER BY clause is added to the
496 -- foreign join so that the local table can be joined using merge join strategy.
497 EXPLAIN (VERBOSE, COSTS OFF)
498         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;
499                                                                        QUERY PLAN                                                                        
500 ---------------------------------------------------------------------------------------------------------------------------------------------------------
501  Limit
502    Output: t1."C 1"
503    ->  Merge Right Join
504          Output: t1."C 1"
505          Inner Unique: true
506          Merge Cond: (t3.c1 = t1."C 1")
507          ->  Foreign Scan
508                Output: t3.c1
509                Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
510                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
511          ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
512                Output: t1."C 1"
513 (12 rows)
514
515 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;
516  C 1 
517 -----
518  101
519  102
520  103
521  104
522  105
523  106
524  107
525  108
526  109
527  110
528 (10 rows)
529
530 -- Test similar to above, except that the full join prevents any equivalence
531 -- classes from being merged. This produces single relation equivalence classes
532 -- included in join restrictions.
533 EXPLAIN (VERBOSE, COSTS OFF)
534         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;
535                                                                             QUERY PLAN                                                                            
536 ------------------------------------------------------------------------------------------------------------------------------------------------------------------
537  Limit
538    Output: t1."C 1", t2.c1, t3.c1
539    ->  Merge Right Join
540          Output: t1."C 1", t2.c1, t3.c1
541          Inner Unique: true
542          Merge Cond: (t3.c1 = t1."C 1")
543          ->  Foreign Scan
544                Output: t3.c1, t2.c1
545                Relations: (public.ft2 t3) LEFT JOIN (public.ft1 t2)
546                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
547          ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
548                Output: t1."C 1"
549 (12 rows)
550
551 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;
552  C 1 | c1  | c1  
553 -----+-----+-----
554  101 | 101 | 101
555  102 | 102 | 102
556  103 | 103 | 103
557  104 | 104 | 104
558  105 | 105 | 105
559  106 | 106 | 106
560  107 | 107 | 107
561  108 | 108 | 108
562  109 | 109 | 109
563  110 | 110 | 110
564 (10 rows)
565
566 -- Test similar to above with all full outer joins
567 EXPLAIN (VERBOSE, COSTS OFF)
568         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;
569                                                                             QUERY PLAN                                                                            
570 ------------------------------------------------------------------------------------------------------------------------------------------------------------------
571  Limit
572    Output: t1."C 1", t2.c1, t3.c1
573    ->  Merge Full Join
574          Output: t1."C 1", t2.c1, t3.c1
575          Inner Unique: true
576          Merge Cond: (t3.c1 = t1."C 1")
577          ->  Foreign Scan
578                Output: t2.c1, t3.c1
579                Relations: (public.ft1 t2) FULL JOIN (public.ft2 t3)
580                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
581          ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
582                Output: t1."C 1"
583 (12 rows)
584
585 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;
586  C 1 | c1  | c1  
587 -----+-----+-----
588  101 | 101 | 101
589  102 | 102 | 102
590  103 | 103 | 103
591  104 | 104 | 104
592  105 | 105 | 105
593  106 | 106 | 106
594  107 | 107 | 107
595  108 | 108 | 108
596  109 | 109 | 109
597  110 | 110 | 110
598 (10 rows)
599
600 RESET enable_hashjoin;
601 RESET enable_nestloop;
602 -- ===================================================================
603 -- WHERE with remotely-executable conditions
604 -- ===================================================================
605 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 1;         -- Var, OpExpr(b), Const
606                                          QUERY PLAN                                          
607 ---------------------------------------------------------------------------------------------
608  Foreign Scan on public.ft1 t1
609    Output: c1, c2, c3, c4, c5, c6, c7, c8
610    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
611 (3 rows)
612
613 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 100 AND t1.c2 = 0; -- BoolExpr
614                                                   QUERY PLAN                                                  
615 --------------------------------------------------------------------------------------------------------------
616  Foreign Scan on public.ft1 t1
617    Output: c1, c2, c3, c4, c5, c6, c7, c8
618    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 100)) AND ((c2 = 0))
619 (3 rows)
620
621 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NULL;        -- NullTest
622                                            QUERY PLAN                                            
623 -------------------------------------------------------------------------------------------------
624  Foreign Scan on public.ft1 t1
625    Output: c1, c2, c3, c4, c5, c6, c7, c8
626    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" IS NULL))
627 (3 rows)
628
629 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL;    -- NullTest
630                                              QUERY PLAN                                              
631 -----------------------------------------------------------------------------------------------------
632  Foreign Scan on public.ft1 t1
633    Output: c1, c2, c3, c4, c5, c6, c7, c8
634    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" IS NOT NULL))
635 (3 rows)
636
637 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr
638                                                      QUERY PLAN                                                      
639 ---------------------------------------------------------------------------------------------------------------------
640  Foreign Scan on public.ft1 t1
641    Output: c1, c2, c3, c4, c5, c6, c7, c8
642    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))
643 (3 rows)
644
645 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1;          -- OpExpr(l)
646                                              QUERY PLAN                                              
647 -----------------------------------------------------------------------------------------------------
648  Foreign Scan on public.ft1 t1
649    Output: c1, c2, c3, c4, c5, c6, c7, c8
650    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = (- "C 1")))
651 (3 rows)
652
653 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE 1 = c1!;           -- OpExpr(r)
654                                                 QUERY PLAN                                                
655 ----------------------------------------------------------------------------------------------------------
656  Foreign Scan on public.ft1 t1
657    Output: c1, c2, c3, c4, c5, c6, c7, c8
658    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((1::numeric = ("C 1" !)))
659 (3 rows)
660
661 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
662                                                                  QUERY PLAN                                                                 
663 --------------------------------------------------------------------------------------------------------------------------------------------
664  Foreign Scan on public.ft1 t1
665    Output: c1, c2, c3, c4, c5, c6, c7, c8
666    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)))
667 (3 rows)
668
669 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr
670                                                         QUERY PLAN                                                         
671 ---------------------------------------------------------------------------------------------------------------------------
672  Foreign Scan on public.ft1 t1
673    Output: c1, c2, c3, c4, c5, c6, c7, c8
674    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)])))
675 (3 rows)
676
677 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- ArrayRef
678                                                       QUERY PLAN                                                      
679 ----------------------------------------------------------------------------------------------------------------------
680  Foreign Scan on public.ft1 t1
681    Output: c1, c2, c3, c4, c5, c6, c7, c8
682    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])))
683 (3 rows)
684
685 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar';  -- check special chars
686                                                  QUERY PLAN                                                  
687 -------------------------------------------------------------------------------------------------------------
688  Foreign Scan on public.ft1 t1
689    Output: c1, c2, c3, c4, c5, c6, c7, c8
690    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c6 = E'foo''s\\bar'::text))
691 (3 rows)
692
693 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c8 = 'foo';  -- can't be sent to remote
694                                QUERY PLAN                                
695 -------------------------------------------------------------------------
696  Foreign Scan on public.ft1 t1
697    Output: c1, c2, c3, c4, c5, c6, c7, c8
698    Filter: (t1.c8 = 'foo'::user_enum)
699    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
700 (4 rows)
701
702 -- parameterized remote path for foreign table
703 EXPLAIN (VERBOSE, COSTS OFF)
704   SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2;
705                                                  QUERY PLAN                                                  
706 -------------------------------------------------------------------------------------------------------------
707  Nested Loop
708    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
709    ->  Index Scan using t1_pkey on "S 1"."T 1" a
710          Output: a."C 1", a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8
711          Index Cond: (a."C 1" = 47)
712    ->  Foreign Scan on public.ft2 b
713          Output: b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8
714          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
715 (8 rows)
716
717 SELECT * FROM ft2 a, ft2 b WHERE a.c1 = 47 AND b.c1 = a.c2;
718  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
719 ----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----
720  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
721 (1 row)
722
723 -- check both safe and unsafe join conditions
724 EXPLAIN (VERBOSE, COSTS OFF)
725   SELECT * FROM ft2 a, ft2 b
726   WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7);
727                                                  QUERY PLAN                                                  
728 -------------------------------------------------------------------------------------------------------------
729  Nested Loop
730    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
731    ->  Foreign Scan on public.ft2 a
732          Output: a.c1, a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8
733          Filter: (a.c8 = 'foo'::user_enum)
734          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c2 = 6))
735    ->  Foreign Scan on public.ft2 b
736          Output: b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8
737          Filter: (upper((a.c7)::text) = (b.c7)::text)
738          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
739 (10 rows)
740
741 SELECT * FROM ft2 a, ft2 b
742 WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7);
743  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
744 -----+----+-------+------------------------------+--------------------------+----+------------+-----+-----+----+-------+------------------------------+--------------------------+----+------------+-----
745    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
746   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
747   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
748   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
749   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
750   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
751   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
752   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
753   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
754   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
755  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
756  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
757  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
758  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
759  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
760  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
761  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
762  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
763  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
764  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
765  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
766  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
767  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
768  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
769  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
770  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
771  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
772  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
773  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
774  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
775  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
776  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
777  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
778  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
779  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
780  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
781  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
782  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
783  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
784  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
785  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
786  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
787  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
788  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
789  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
790  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
791  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
792  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
793  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
794  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
795  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
796  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
797  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
798  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
799  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
800  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
801  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
802  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
803  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
804  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
805  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
806  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
807  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
808  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
809  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
810  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
811  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
812  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
813  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
814  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
815  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
816  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
817  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
818  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
819  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
820  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
821  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
822  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
823  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
824  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
825  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
826  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
827  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
828  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
829  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
830  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
831  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
832  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
833  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
834  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
835  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
836  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
837  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
838  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
839  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
840  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
841  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
842  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
843  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
844  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
845 (100 rows)
846
847 -- bug before 9.3.5 due to sloppy handling of remote-estimate parameters
848 SELECT * FROM ft1 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft2 WHERE c1 < 5));
849  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
850 ----+----+-------+------------------------------+--------------------------+----+------------+-----
851   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
852   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
853   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
854   4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
855 (4 rows)
856
857 SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5));
858  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
859 ----+----+-------+------------------------------+--------------------------+----+------------+-----
860   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
861   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
862   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
863   4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
864 (4 rows)
865
866 -- we should not push order by clause with volatile expressions or unsafe
867 -- collations
868 EXPLAIN (VERBOSE, COSTS OFF)
869         SELECT * FROM ft2 ORDER BY ft2.c1, random();
870                                   QUERY PLAN                                   
871 -------------------------------------------------------------------------------
872  Sort
873    Output: c1, c2, c3, c4, c5, c6, c7, c8, (random())
874    Sort Key: ft2.c1, (random())
875    ->  Foreign Scan on public.ft2
876          Output: c1, c2, c3, c4, c5, c6, c7, c8, random()
877          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
878 (6 rows)
879
880 EXPLAIN (VERBOSE, COSTS OFF)
881         SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C";
882                                   QUERY PLAN                                   
883 -------------------------------------------------------------------------------
884  Sort
885    Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text)
886    Sort Key: ft2.c1, ft2.c3 COLLATE "C"
887    ->  Foreign Scan on public.ft2
888          Output: c1, c2, c3, c4, c5, c6, c7, c8, c3
889          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
890 (6 rows)
891
892 -- user-defined operator/function
893 CREATE FUNCTION postgres_fdw_abs(int) RETURNS int AS $$
894 BEGIN
895 RETURN abs($1);
896 END
897 $$ LANGUAGE plpgsql IMMUTABLE;
898 CREATE OPERATOR === (
899     LEFTARG = int,
900     RIGHTARG = int,
901     PROCEDURE = int4eq,
902     COMMUTATOR = ===
903 );
904 -- built-in operators and functions can be shipped for remote execution
905 EXPLAIN (VERBOSE, COSTS OFF)
906   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
907                                 QUERY PLAN                                 
908 ---------------------------------------------------------------------------
909  Foreign Scan
910    Output: (count(c3))
911    Relations: Aggregate on (public.ft1 t1)
912    Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" = abs(c2)))
913 (4 rows)
914
915 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
916  count 
917 -------
918      9
919 (1 row)
920
921 EXPLAIN (VERBOSE, COSTS OFF)
922   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
923                               QUERY PLAN                              
924 ----------------------------------------------------------------------
925  Foreign Scan
926    Output: (count(c3))
927    Relations: Aggregate on (public.ft1 t1)
928    Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" = c2))
929 (4 rows)
930
931 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
932  count 
933 -------
934      9
935 (1 row)
936
937 -- by default, user-defined ones cannot
938 EXPLAIN (VERBOSE, COSTS OFF)
939   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
940                         QUERY PLAN                         
941 -----------------------------------------------------------
942  Aggregate
943    Output: count(c3)
944    ->  Foreign Scan on public.ft1 t1
945          Output: c3
946          Filter: (t1.c1 = postgres_fdw_abs(t1.c2))
947          Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
948 (6 rows)
949
950 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
951  count 
952 -------
953      9
954 (1 row)
955
956 EXPLAIN (VERBOSE, COSTS OFF)
957   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
958                         QUERY PLAN                         
959 -----------------------------------------------------------
960  Aggregate
961    Output: count(c3)
962    ->  Foreign Scan on public.ft1 t1
963          Output: c3
964          Filter: (t1.c1 === t1.c2)
965          Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
966 (6 rows)
967
968 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
969  count 
970 -------
971      9
972 (1 row)
973
974 -- but let's put them in an extension ...
975 ALTER EXTENSION postgres_fdw ADD FUNCTION postgres_fdw_abs(int);
976 ALTER EXTENSION postgres_fdw ADD OPERATOR === (int, int);
977 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
978 -- ... now they can be shipped
979 EXPLAIN (VERBOSE, COSTS OFF)
980   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
981                                           QUERY PLAN                                           
982 -----------------------------------------------------------------------------------------------
983  Foreign Scan
984    Output: (count(c3))
985    Relations: Aggregate on (public.ft1 t1)
986    Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" = public.postgres_fdw_abs(c2)))
987 (4 rows)
988
989 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
990  count 
991 -------
992      9
993 (1 row)
994
995 EXPLAIN (VERBOSE, COSTS OFF)
996   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
997                                        QUERY PLAN                                        
998 -----------------------------------------------------------------------------------------
999  Foreign Scan
1000    Output: (count(c3))
1001    Relations: Aggregate on (public.ft1 t1)
1002    Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2))
1003 (4 rows)
1004
1005 SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
1006  count 
1007 -------
1008      9
1009 (1 row)
1010
1011 -- ===================================================================
1012 -- JOIN queries
1013 -- ===================================================================
1014 -- Analyze ft4 and ft5 so that we have better statistics. These tables do not
1015 -- have use_remote_estimate set.
1016 ANALYZE ft4;
1017 ANALYZE ft5;
1018 -- join two tables
1019 EXPLAIN (VERBOSE, COSTS OFF)
1020 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
1021                                                                                         QUERY PLAN                                                                                        
1022 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1023  Limit
1024    Output: t1.c1, t2.c1, t1.c3
1025    ->  Foreign Scan
1026          Output: t1.c1, t2.c1, t1.c3
1027          Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1028          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
1029 (6 rows)
1030
1031 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
1032  c1  | c1  
1033 -----+-----
1034  101 | 101
1035  102 | 102
1036  103 | 103
1037  104 | 104
1038  105 | 105
1039  106 | 106
1040  107 | 107
1041  108 | 108
1042  109 | 109
1043  110 | 110
1044 (10 rows)
1045
1046 -- join three tables
1047 EXPLAIN (VERBOSE, COSTS OFF)
1048 SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10;
1049                                                                                             QUERY PLAN                                                                                             
1050 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1051  Limit
1052    Output: t1.c1, t2.c2, t3.c3, t1.c3
1053    ->  Sort
1054          Output: t1.c1, t2.c2, t3.c3, t1.c3
1055          Sort Key: t1.c3, t1.c1
1056          ->  Foreign Scan
1057                Output: t1.c1, t2.c2, t3.c3, t1.c3
1058                Relations: ((public.ft1 t1) INNER JOIN (public.ft2 t2)) INNER JOIN (public.ft4 t3)
1059                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))))
1060 (9 rows)
1061
1062 SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10;
1063  c1 | c2 |   c3   
1064 ----+----+--------
1065  22 |  2 | AAA022
1066  24 |  4 | AAA024
1067  26 |  6 | AAA026
1068  28 |  8 | AAA028
1069  30 |  0 | AAA030
1070  32 |  2 | AAA032
1071  34 |  4 | AAA034
1072  36 |  6 | AAA036
1073  38 |  8 | AAA038
1074  40 |  0 | AAA040
1075 (10 rows)
1076
1077 -- left outer join
1078 EXPLAIN (VERBOSE, COSTS OFF)
1079 SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
1080                                                                             QUERY PLAN                                                                             
1081 -------------------------------------------------------------------------------------------------------------------------------------------------------------------
1082  Limit
1083    Output: t1.c1, t2.c1
1084    ->  Foreign Scan
1085          Output: t1.c1, t2.c1
1086          Relations: (public.ft4 t1) LEFT JOIN (public.ft5 t2)
1087          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
1088 (6 rows)
1089
1090 SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
1091  c1 | c1 
1092 ----+----
1093  22 |   
1094  24 | 24
1095  26 |   
1096  28 |   
1097  30 | 30
1098  32 |   
1099  34 |   
1100  36 | 36
1101  38 |   
1102  40 |   
1103 (10 rows)
1104
1105 -- left outer join three tables
1106 EXPLAIN (VERBOSE, COSTS OFF)
1107 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1108                                                                                      QUERY PLAN                                                                                     
1109 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1110  Limit
1111    Output: t1.c1, t2.c2, t3.c3
1112    ->  Foreign Scan
1113          Output: t1.c1, t2.c2, t3.c3
1114          Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
1115          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))))
1116 (6 rows)
1117
1118 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1119  c1 | c2 |   c3   
1120 ----+----+--------
1121  11 |  1 | 
1122  12 |  2 | AAA012
1123  13 |  3 | 
1124  14 |  4 | AAA014
1125  15 |  5 | 
1126  16 |  6 | AAA016
1127  17 |  7 | 
1128  18 |  8 | AAA018
1129  19 |  9 | 
1130  20 |  0 | AAA020
1131 (10 rows)
1132
1133 -- left outer join + placement of clauses.
1134 -- clauses within the nullable side are not pulled up, but top level clause on
1135 -- non-nullable side is pushed into non-nullable side
1136 EXPLAIN (VERBOSE, COSTS OFF)
1137 SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10;
1138                                                                           QUERY PLAN                                                                           
1139 ---------------------------------------------------------------------------------------------------------------------------------------------------------------
1140  Foreign Scan
1141    Output: t1.c1, t1.c2, ft5.c1, ft5.c2
1142    Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
1143    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))
1144 (4 rows)
1145
1146 SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10;
1147  c1 | c2 | c1 | c2 
1148 ----+----+----+----
1149   2 |  3 |    |   
1150   4 |  5 |    |   
1151   6 |  7 |  6 |  7
1152   8 |  9 |    |   
1153 (4 rows)
1154
1155 -- clauses within the nullable side are not pulled up, but the top level clause
1156 -- on nullable side is not pushed down into nullable side
1157 EXPLAIN (VERBOSE, COSTS OFF)
1158 SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1)
1159                         WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
1160                                                                                               QUERY PLAN                                                                                               
1161 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1162  Foreign Scan
1163    Output: t1.c1, t1.c2, ft5.c1, ft5.c2
1164    Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
1165    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))
1166 (4 rows)
1167
1168 SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1)
1169                         WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
1170  c1 | c2 | c1 | c2 
1171 ----+----+----+----
1172   2 |  3 |    |   
1173   4 |  5 |    |   
1174   6 |  7 |  6 |  7
1175   8 |  9 |    |   
1176 (4 rows)
1177
1178 -- right outer join
1179 EXPLAIN (VERBOSE, COSTS OFF)
1180 SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10;
1181                                                                             QUERY PLAN                                                                             
1182 -------------------------------------------------------------------------------------------------------------------------------------------------------------------
1183  Limit
1184    Output: t1.c1, t2.c1
1185    ->  Foreign Scan
1186          Output: t1.c1, t2.c1
1187          Relations: (public.ft4 t2) LEFT JOIN (public.ft5 t1)
1188          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
1189 (6 rows)
1190
1191 SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10;
1192  c1 | c1 
1193 ----+----
1194     | 22
1195  24 | 24
1196     | 26
1197     | 28
1198  30 | 30
1199     | 32
1200     | 34
1201  36 | 36
1202     | 38
1203     | 40
1204 (10 rows)
1205
1206 -- right outer join three tables
1207 EXPLAIN (VERBOSE, COSTS OFF)
1208 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1209                                                                                      QUERY PLAN                                                                                     
1210 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1211  Limit
1212    Output: t1.c1, t2.c2, t3.c3
1213    ->  Foreign Scan
1214          Output: t1.c1, t2.c2, t3.c3
1215          Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
1216          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"))))
1217 (6 rows)
1218
1219 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1220  c1 | c2 |   c3   
1221 ----+----+--------
1222  22 |  2 | AAA022
1223  24 |  4 | AAA024
1224  26 |  6 | AAA026
1225  28 |  8 | AAA028
1226  30 |  0 | AAA030
1227  32 |  2 | AAA032
1228  34 |  4 | AAA034
1229  36 |  6 | AAA036
1230  38 |  8 | AAA038
1231  40 |  0 | AAA040
1232 (10 rows)
1233
1234 -- full outer join
1235 EXPLAIN (VERBOSE, COSTS OFF)
1236 SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10;
1237                                                                             QUERY PLAN                                                                             
1238 -------------------------------------------------------------------------------------------------------------------------------------------------------------------
1239  Limit
1240    Output: t1.c1, t2.c1
1241    ->  Foreign Scan
1242          Output: t1.c1, t2.c1
1243          Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
1244          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
1245 (6 rows)
1246
1247 SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10;
1248  c1  | c1 
1249 -----+----
1250   92 |   
1251   94 |   
1252   96 | 96
1253   98 |   
1254  100 |   
1255      |  3
1256      |  9
1257      | 15
1258      | 21
1259      | 27
1260 (10 rows)
1261
1262 -- full outer join with restrictions on the joining relations
1263 -- a. the joining relations are both base relations
1264 EXPLAIN (VERBOSE, COSTS OFF)
1265 SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1;
1266                                                                                                                                   QUERY PLAN                                                                                                                                   
1267 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1268  Foreign Scan
1269    Output: ft4.c1, ft5.c1
1270    Relations: (public.ft4) FULL JOIN (public.ft5)
1271    Remote SQL: SELECT s4.c1, s5.c1 FROM ((SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s4(c1) FULL JOIN (SELECT c1 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s5(c1) ON (((s4.c1 = s5.c1)))) ORDER BY s4.c1 ASC NULLS LAST, s5.c1 ASC NULLS LAST
1272 (4 rows)
1273
1274 SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1;
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 EXPLAIN (VERBOSE, COSTS OFF)
1288 SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10;
1289                                                                                                QUERY PLAN                                                                                               
1290 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1291  Limit
1292    Output: 1
1293    ->  Foreign Scan
1294          Output: 1
1295          Relations: (public.ft4) FULL JOIN (public.ft5)
1296          Remote SQL: SELECT NULL FROM ((SELECT NULL FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s4 FULL JOIN (SELECT NULL FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s5 ON (TRUE))
1297 (6 rows)
1298
1299 SELECT 1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (TRUE) OFFSET 10 LIMIT 10;
1300  ?column? 
1301 ----------
1302         1
1303         1
1304         1
1305         1
1306         1
1307         1
1308         1
1309         1
1310         1
1311         1
1312 (10 rows)
1313
1314 -- b. one of the joining relations is a base relation and the other is a join
1315 -- relation
1316 EXPLAIN (VERBOSE, COSTS OFF)
1317 SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b;
1318                                                                                                                                                                                      QUERY PLAN                                                                                                                                                                                      
1319 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1320  Foreign Scan
1321    Output: ft4.c1, t2.c1, t3.c1
1322    Relations: (public.ft4) FULL JOIN ((public.ft4 t2) LEFT JOIN (public.ft5 t3))
1323    Remote SQL: SELECT s4.c1, s8.c1, s8.c2 FROM ((SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s4(c1) FULL JOIN (SELECT r5.c1, r6.c1 FROM ("S 1"."T 3" r5 LEFT JOIN "S 1"."T 4" r6 ON (((r5.c1 = r6.c1)))) WHERE ((r5.c1 >= 50)) AND ((r5.c1 <= 60))) s8(c1, c2) ON (((s4.c1 = s8.c1)))) ORDER BY s4.c1 ASC NULLS LAST, s8.c1 ASC NULLS LAST, s8.c2 ASC NULLS LAST
1324 (4 rows)
1325
1326 SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM ft4 t2 LEFT JOIN ft5 t3 ON (t2.c1 = t3.c1) WHERE (t2.c1 between 50 and 60)) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b;
1327  c1 | a  | b  
1328 ----+----+----
1329  50 | 50 |   
1330  52 | 52 |   
1331  54 | 54 | 54
1332  56 | 56 |   
1333  58 | 58 |   
1334  60 | 60 | 60
1335 (6 rows)
1336
1337 -- c. test deparsing the remote query as nested subqueries
1338 EXPLAIN (VERBOSE, COSTS OFF)
1339 SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b;
1340                                                                                                                                                                                                                                                      QUERY PLAN                                                                                                                                                                                                                                                     
1341 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1342  Foreign Scan
1343    Output: ft4.c1, ft4_1.c1, ft5.c1
1344    Relations: (public.ft4) FULL JOIN ((public.ft4) FULL JOIN (public.ft5))
1345    Remote SQL: SELECT s4.c1, s10.c1, s10.c2 FROM ((SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s4(c1) FULL JOIN (SELECT s8.c1, s9.c1 FROM ((SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s8(c1) FULL JOIN (SELECT c1 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s9(c1) ON (((s8.c1 = s9.c1)))) WHERE (((s8.c1 IS NULL) OR (s8.c1 IS NOT NULL)))) s10(c1, c2) ON (((s4.c1 = s10.c1)))) ORDER BY s4.c1 ASC NULLS LAST, s10.c1 ASC NULLS LAST, s10.c2 ASC NULLS LAST
1346 (4 rows)
1347
1348 SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (t1.c1 = ss.a) ORDER BY t1.c1, ss.a, ss.b;
1349  c1 | a  | b  
1350 ----+----+----
1351  50 | 50 |   
1352  52 | 52 |   
1353  54 | 54 | 54
1354  56 | 56 |   
1355  58 | 58 |   
1356  60 | 60 | 60
1357     |    | 51
1358     |    | 57
1359 (8 rows)
1360
1361 -- d. test deparsing rowmarked relations as subqueries
1362 EXPLAIN (VERBOSE, COSTS OFF)
1363 SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1;
1364                                                                                                                                                                                              QUERY PLAN                                                                                                                                                                                             
1365 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1366  LockRows
1367    Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".ctid, ft4.*, ft5.*
1368    ->  Nested Loop
1369          Output: "T 3".c1, ft4.c1, ft5.c1, "T 3".ctid, ft4.*, ft5.*
1370          ->  Foreign Scan
1371                Output: ft4.c1, ft4.*, ft5.c1, ft5.*
1372                Relations: (public.ft4) FULL JOIN (public.ft5)
1373                Remote SQL: SELECT s8.c1, s8.c2, s9.c1, s9.c2 FROM ((SELECT c1, ROW(c1, c2, c3) FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s8(c1, c2) FULL JOIN (SELECT c1, ROW(c1, c2, c3) FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s9(c1, c2) ON (((s8.c1 = s9.c1)))) WHERE (((s8.c1 IS NULL) OR (s8.c1 IS NOT NULL))) ORDER BY s8.c1 ASC NULLS LAST, s9.c1 ASC NULLS LAST
1374                ->  Sort
1375                      Output: ft4.c1, ft4.*, ft5.c1, ft5.*
1376                      Sort Key: ft4.c1, ft5.c1
1377                      ->  Hash Full Join
1378                            Output: ft4.c1, ft4.*, ft5.c1, ft5.*
1379                            Hash Cond: (ft4.c1 = ft5.c1)
1380                            Filter: ((ft4.c1 IS NULL) OR (ft4.c1 IS NOT NULL))
1381                            ->  Foreign Scan on public.ft4
1382                                  Output: ft4.c1, ft4.*
1383                                  Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))
1384                            ->  Hash
1385                                  Output: ft5.c1, ft5.*
1386                                  ->  Foreign Scan on public.ft5
1387                                        Output: ft5.c1, ft5.*
1388                                        Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))
1389          ->  Materialize
1390                Output: "T 3".c1, "T 3".ctid
1391                ->  Seq Scan on "S 1"."T 3"
1392                      Output: "T 3".c1, "T 3".ctid
1393                      Filter: ("T 3".c1 = 50)
1394 (28 rows)
1395
1396 SELECT t1.c1, ss.a, ss.b FROM (SELECT c1 FROM "S 1"."T 3" WHERE c1 = 50) t1 INNER JOIN (SELECT t2.c1, t3.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t2 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t3 ON (t2.c1 = t3.c1) WHERE t2.c1 IS NULL OR t2.c1 IS NOT NULL) ss(a, b) ON (TRUE) ORDER BY t1.c1, ss.a, ss.b FOR UPDATE OF t1;
1397  c1 | a  | b  
1398 ----+----+----
1399  50 | 50 |   
1400  50 | 52 |   
1401  50 | 54 | 54
1402  50 | 56 |   
1403  50 | 58 |   
1404  50 | 60 | 60
1405  50 |    | 51
1406  50 |    | 57
1407 (8 rows)
1408
1409 -- full outer join + inner join
1410 EXPLAIN (VERBOSE, COSTS OFF)
1411 SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10;
1412                                                                                                                                            QUERY PLAN                                                                                                                                            
1413 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1414  Limit
1415    Output: t1.c1, t2.c1, t3.c1
1416    ->  Foreign Scan
1417          Output: t1.c1, t2.c1, t3.c1
1418          Relations: ((public.ft4 t1) INNER JOIN (public.ft5 t2)) FULL JOIN (public.ft4 t3)
1419          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
1420 (6 rows)
1421
1422 SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10;
1423  c1 | c1 | c1 
1424 ----+----+----
1425  52 | 51 |   
1426  58 | 57 |   
1427     |    |  2
1428     |    |  4
1429     |    |  6
1430     |    |  8
1431     |    | 10
1432     |    | 12
1433     |    | 14
1434     |    | 16
1435 (10 rows)
1436
1437 -- full outer join three tables
1438 EXPLAIN (VERBOSE, COSTS OFF)
1439 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1440                                                                                      QUERY PLAN                                                                                     
1441 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1442  Limit
1443    Output: t1.c1, t2.c2, t3.c3
1444    ->  Foreign Scan
1445          Output: t1.c1, t2.c2, t3.c3
1446          Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
1447          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))))
1448 (6 rows)
1449
1450 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1451  c1 | c2 |   c3   
1452 ----+----+--------
1453  11 |  1 | 
1454  12 |  2 | AAA012
1455  13 |  3 | 
1456  14 |  4 | AAA014
1457  15 |  5 | 
1458  16 |  6 | AAA016
1459  17 |  7 | 
1460  18 |  8 | AAA018
1461  19 |  9 | 
1462  20 |  0 | AAA020
1463 (10 rows)
1464
1465 -- full outer join + right outer join
1466 EXPLAIN (VERBOSE, COSTS OFF)
1467 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1468                                                                                      QUERY PLAN                                                                                     
1469 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1470  Limit
1471    Output: t1.c1, t2.c2, t3.c3
1472    ->  Foreign Scan
1473          Output: t1.c1, t2.c2, t3.c3
1474          Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
1475          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"))))
1476 (6 rows)
1477
1478 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1479  c1 | c2 |   c3   
1480 ----+----+--------
1481  22 |  2 | AAA022
1482  24 |  4 | AAA024
1483  26 |  6 | AAA026
1484  28 |  8 | AAA028
1485  30 |  0 | AAA030
1486  32 |  2 | AAA032
1487  34 |  4 | AAA034
1488  36 |  6 | AAA036
1489  38 |  8 | AAA038
1490  40 |  0 | AAA040
1491 (10 rows)
1492
1493 -- right outer join + full outer join
1494 EXPLAIN (VERBOSE, COSTS OFF)
1495 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1496                                                                                      QUERY PLAN                                                                                     
1497 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1498  Limit
1499    Output: t1.c1, t2.c2, t3.c3
1500    ->  Foreign Scan
1501          Output: t1.c1, t2.c2, t3.c3
1502          Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) FULL JOIN (public.ft4 t3)
1503          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))))
1504 (6 rows)
1505
1506 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1507  c1 | c2 |   c3   
1508 ----+----+--------
1509  11 |  1 | 
1510  12 |  2 | AAA012
1511  13 |  3 | 
1512  14 |  4 | AAA014
1513  15 |  5 | 
1514  16 |  6 | AAA016
1515  17 |  7 | 
1516  18 |  8 | AAA018
1517  19 |  9 | 
1518  20 |  0 | AAA020
1519 (10 rows)
1520
1521 -- full outer join + left outer join
1522 EXPLAIN (VERBOSE, COSTS OFF)
1523 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1524                                                                                      QUERY PLAN                                                                                     
1525 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1526  Limit
1527    Output: t1.c1, t2.c2, t3.c3
1528    ->  Foreign Scan
1529          Output: t1.c1, t2.c2, t3.c3
1530          Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
1531          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))))
1532 (6 rows)
1533
1534 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1535  c1 | c2 |   c3   
1536 ----+----+--------
1537  11 |  1 | 
1538  12 |  2 | AAA012
1539  13 |  3 | 
1540  14 |  4 | AAA014
1541  15 |  5 | 
1542  16 |  6 | AAA016
1543  17 |  7 | 
1544  18 |  8 | AAA018
1545  19 |  9 | 
1546  20 |  0 | AAA020
1547 (10 rows)
1548
1549 -- left outer join + full outer join
1550 EXPLAIN (VERBOSE, COSTS OFF)
1551 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1552                                                                                      QUERY PLAN                                                                                     
1553 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1554  Limit
1555    Output: t1.c1, t2.c2, t3.c3
1556    ->  Foreign Scan
1557          Output: t1.c1, t2.c2, t3.c3
1558          Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
1559          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))))
1560 (6 rows)
1561
1562 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1563  c1 | c2 |   c3   
1564 ----+----+--------
1565  11 |  1 | 
1566  12 |  2 | AAA012
1567  13 |  3 | 
1568  14 |  4 | AAA014
1569  15 |  5 | 
1570  16 |  6 | AAA016
1571  17 |  7 | 
1572  18 |  8 | AAA018
1573  19 |  9 | 
1574  20 |  0 | AAA020
1575 (10 rows)
1576
1577 -- right outer join + left outer join
1578 EXPLAIN (VERBOSE, COSTS OFF)
1579 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1580                                                                                      QUERY PLAN                                                                                     
1581 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1582  Limit
1583    Output: t1.c1, t2.c2, t3.c3
1584    ->  Foreign Scan
1585          Output: t1.c1, t2.c2, t3.c3
1586          Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) LEFT JOIN (public.ft4 t3)
1587          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))))
1588 (6 rows)
1589
1590 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1591  c1 | c2 |   c3   
1592 ----+----+--------
1593  11 |  1 | 
1594  12 |  2 | AAA012
1595  13 |  3 | 
1596  14 |  4 | AAA014
1597  15 |  5 | 
1598  16 |  6 | AAA016
1599  17 |  7 | 
1600  18 |  8 | AAA018
1601  19 |  9 | 
1602  20 |  0 | AAA020
1603 (10 rows)
1604
1605 -- left outer join + right outer join
1606 EXPLAIN (VERBOSE, COSTS OFF)
1607 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1608                                                                                      QUERY PLAN                                                                                      
1609 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1610  Limit
1611    Output: t1.c1, t2.c2, t3.c3
1612    ->  Foreign Scan
1613          Output: t1.c1, t2.c2, t3.c3
1614          Relations: (public.ft4 t3) LEFT JOIN ((public.ft2 t1) INNER JOIN (public.ft2 t2))
1615          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))))
1616 (6 rows)
1617
1618 SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
1619  c1 | c2 |   c3   
1620 ----+----+--------
1621  22 |  2 | AAA022
1622  24 |  4 | AAA024
1623  26 |  6 | AAA026
1624  28 |  8 | AAA028
1625  30 |  0 | AAA030
1626  32 |  2 | AAA032
1627  34 |  4 | AAA034
1628  36 |  6 | AAA036
1629  38 |  8 | AAA038
1630  40 |  0 | AAA040
1631 (10 rows)
1632
1633 -- full outer join + WHERE clause, only matched rows
1634 EXPLAIN (VERBOSE, COSTS OFF)
1635 SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
1636                                                                             QUERY PLAN                                                                            
1637 ------------------------------------------------------------------------------------------------------------------------------------------------------------------
1638  Limit
1639    Output: t1.c1, t2.c1
1640    ->  Sort
1641          Output: t1.c1, t2.c1
1642          Sort Key: t1.c1, t2.c1
1643          ->  Foreign Scan
1644                Output: t1.c1, t2.c1
1645                Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
1646                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)))
1647 (9 rows)
1648
1649 SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
1650  c1 | c1 
1651 ----+----
1652  66 | 66
1653  72 | 72
1654  78 | 78
1655  84 | 84
1656  90 | 90
1657  96 | 96
1658     |  3
1659     |  9
1660     | 15
1661     | 21
1662 (10 rows)
1663
1664 -- full outer join + WHERE clause with shippable extensions set
1665 EXPLAIN (VERBOSE, COSTS OFF)
1666 SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE postgres_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10;
1667                                                                                   QUERY PLAN                                                                                   
1668 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1669  Limit
1670    Output: t1.c1, t2.c2, t1.c3
1671    ->  Foreign Scan
1672          Output: t1.c1, t2.c2, t1.c3
1673          Relations: (public.ft1 t1) FULL JOIN (public.ft2 t2)
1674          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))
1675 (6 rows)
1676
1677 ALTER SERVER loopback OPTIONS (DROP extensions);
1678 -- full outer join + WHERE clause with shippable extensions not set
1679 EXPLAIN (VERBOSE, COSTS OFF)
1680 SELECT t1.c1, t2.c2, t1.c3 FROM ft1 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE postgres_fdw_abs(t1.c1) > 0 OFFSET 10 LIMIT 10;
1681                                                           QUERY PLAN                                                           
1682 -------------------------------------------------------------------------------------------------------------------------------
1683  Limit
1684    Output: t1.c1, t2.c2, t1.c3
1685    ->  Foreign Scan
1686          Output: t1.c1, t2.c2, t1.c3
1687          Filter: (postgres_fdw_abs(t1.c1) > 0)
1688          Relations: (public.ft1 t1) FULL JOIN (public.ft2 t2)
1689          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"))))
1690 (7 rows)
1691
1692 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
1693 -- join two tables with FOR UPDATE clause
1694 -- tests whole-row reference for row marks
1695 EXPLAIN (VERBOSE, COSTS OFF)
1696 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1;
1697                                                                                                                                                                                                                QUERY PLAN                                                                                                                                                                                                                
1698 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1699  Limit
1700    Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1701    ->  LockRows
1702          Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1703          ->  Foreign Scan
1704                Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1705                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1706                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
1707                ->  Sort
1708                      Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1709                      Sort Key: t1.c3, t1.c1
1710                      ->  Merge Join
1711                            Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1712                            Merge Cond: (t1.c1 = t2.c1)
1713                            ->  Sort
1714                                  Output: t1.c1, t1.c3, t1.*
1715                                  Sort Key: t1.c1
1716                                  ->  Foreign Scan on public.ft1 t1
1717                                        Output: t1.c1, t1.c3, t1.*
1718                                        Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
1719                            ->  Sort
1720                                  Output: t2.c1, t2.*
1721                                  Sort Key: t2.c1
1722                                  ->  Foreign Scan on public.ft2 t2
1723                                        Output: t2.c1, t2.*
1724                                        Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1725 (26 rows)
1726
1727 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1;
1728  c1  | c1  
1729 -----+-----
1730  101 | 101
1731  102 | 102
1732  103 | 103
1733  104 | 104
1734  105 | 105
1735  106 | 106
1736  107 | 107
1737  108 | 108
1738  109 | 109
1739  110 | 110
1740 (10 rows)
1741
1742 EXPLAIN (VERBOSE, COSTS OFF)
1743 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE;
1744                                                                                                                                                                                                                         QUERY PLAN                                                                                                                                                                                                                        
1745 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1746  Limit
1747    Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1748    ->  LockRows
1749          Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1750          ->  Foreign Scan
1751                Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1752                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1753                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
1754                ->  Sort
1755                      Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1756                      Sort Key: t1.c3, t1.c1
1757                      ->  Merge Join
1758                            Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1759                            Merge Cond: (t1.c1 = t2.c1)
1760                            ->  Sort
1761                                  Output: t1.c1, t1.c3, t1.*
1762                                  Sort Key: t1.c1
1763                                  ->  Foreign Scan on public.ft1 t1
1764                                        Output: t1.c1, t1.c3, t1.*
1765                                        Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
1766                            ->  Sort
1767                                  Output: t2.c1, t2.*
1768                                  Sort Key: t2.c1
1769                                  ->  Foreign Scan on public.ft2 t2
1770                                        Output: t2.c1, t2.*
1771                                        Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
1772 (26 rows)
1773
1774 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE;
1775  c1  | c1  
1776 -----+-----
1777  101 | 101
1778  102 | 102
1779  103 | 103
1780  104 | 104
1781  105 | 105
1782  106 | 106
1783  107 | 107
1784  108 | 108
1785  109 | 109
1786  110 | 110
1787 (10 rows)
1788
1789 -- join two tables with FOR SHARE clause
1790 EXPLAIN (VERBOSE, COSTS OFF)
1791 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1;
1792                                                                                                                                                                                                                QUERY PLAN                                                                                                                                                                                                               
1793 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1794  Limit
1795    Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1796    ->  LockRows
1797          Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1798          ->  Foreign Scan
1799                Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1800                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1801                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
1802                ->  Sort
1803                      Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1804                      Sort Key: t1.c3, t1.c1
1805                      ->  Merge Join
1806                            Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1807                            Merge Cond: (t1.c1 = t2.c1)
1808                            ->  Sort
1809                                  Output: t1.c1, t1.c3, t1.*
1810                                  Sort Key: t1.c1
1811                                  ->  Foreign Scan on public.ft1 t1
1812                                        Output: t1.c1, t1.c3, t1.*
1813                                        Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
1814                            ->  Sort
1815                                  Output: t2.c1, t2.*
1816                                  Sort Key: t2.c1
1817                                  ->  Foreign Scan on public.ft2 t2
1818                                        Output: t2.c1, t2.*
1819                                        Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
1820 (26 rows)
1821
1822 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1;
1823  c1  | c1  
1824 -----+-----
1825  101 | 101
1826  102 | 102
1827  103 | 103
1828  104 | 104
1829  105 | 105
1830  106 | 106
1831  107 | 107
1832  108 | 108
1833  109 | 109
1834  110 | 110
1835 (10 rows)
1836
1837 EXPLAIN (VERBOSE, COSTS OFF)
1838 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE;
1839                                                                                                                                                                                                                        QUERY PLAN                                                                                                                                                                                                                       
1840 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1841  Limit
1842    Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1843    ->  LockRows
1844          Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1845          ->  Foreign Scan
1846                Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
1847                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1848                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
1849                ->  Sort
1850                      Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1851                      Sort Key: t1.c3, t1.c1
1852                      ->  Merge Join
1853                            Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
1854                            Merge Cond: (t1.c1 = t2.c1)
1855                            ->  Sort
1856                                  Output: t1.c1, t1.c3, t1.*
1857                                  Sort Key: t1.c1
1858                                  ->  Foreign Scan on public.ft1 t1
1859                                        Output: t1.c1, t1.c3, t1.*
1860                                        Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
1861                            ->  Sort
1862                                  Output: t2.c1, t2.*
1863                                  Sort Key: t2.c1
1864                                  ->  Foreign Scan on public.ft2 t2
1865                                        Output: t2.c1, t2.*
1866                                        Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
1867 (26 rows)
1868
1869 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE;
1870  c1  | c1  
1871 -----+-----
1872  101 | 101
1873  102 | 102
1874  103 | 103
1875  104 | 104
1876  105 | 105
1877  106 | 106
1878  107 | 107
1879  108 | 108
1880  109 | 109
1881  110 | 110
1882 (10 rows)
1883
1884 -- join in CTE
1885 EXPLAIN (VERBOSE, COSTS OFF)
1886 WITH 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;
1887                                                              QUERY PLAN                                                              
1888 -------------------------------------------------------------------------------------------------------------------------------------
1889  Limit
1890    Output: t.c1_1, t.c2_1, t.c1_3
1891    CTE t
1892      ->  Foreign Scan
1893            Output: t1.c1, t1.c3, t2.c1
1894            Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1895            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"))))
1896    ->  Sort
1897          Output: t.c1_1, t.c2_1, t.c1_3
1898          Sort Key: t.c1_3, t.c1_1
1899          ->  CTE Scan on t
1900                Output: t.c1_1, t.c2_1, t.c1_3
1901 (12 rows)
1902
1903 WITH 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;
1904  c1_1 | c2_1 
1905 ------+------
1906   101 |  101
1907   102 |  102
1908   103 |  103
1909   104 |  104
1910   105 |  105
1911   106 |  106
1912   107 |  107
1913   108 |  108
1914   109 |  109
1915   110 |  110
1916 (10 rows)
1917
1918 -- ctid with whole-row reference
1919 EXPLAIN (VERBOSE, COSTS OFF)
1920 SELECT t1.ctid, t1, t2, t1.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
1921                                                                                                                                                                                                    QUERY PLAN                                                                                                                                                                                                    
1922 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
1923  Limit
1924    Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
1925    ->  Foreign Scan
1926          Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
1927          Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
1928          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
1929 (6 rows)
1930
1931 -- SEMI JOIN, not pushed down
1932 EXPLAIN (VERBOSE, COSTS OFF)
1933 SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
1934                                       QUERY PLAN                                       
1935 ---------------------------------------------------------------------------------------
1936  Limit
1937    Output: t1.c1
1938    ->  Merge Semi Join
1939          Output: t1.c1
1940          Merge Cond: (t1.c1 = t2.c1)
1941          ->  Foreign Scan on public.ft1 t1
1942                Output: t1.c1
1943                Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1944          ->  Foreign Scan on public.ft2 t2
1945                Output: t2.c1
1946                Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1947 (11 rows)
1948
1949 SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
1950  c1  
1951 -----
1952  101
1953  102
1954  103
1955  104
1956  105
1957  106
1958  107
1959  108
1960  109
1961  110
1962 (10 rows)
1963
1964 -- ANTI JOIN, not pushed down
1965 EXPLAIN (VERBOSE, COSTS OFF)
1966 SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
1967                                       QUERY PLAN                                       
1968 ---------------------------------------------------------------------------------------
1969  Limit
1970    Output: t1.c1
1971    ->  Merge Anti Join
1972          Output: t1.c1
1973          Merge Cond: (t1.c1 = t2.c2)
1974          ->  Foreign Scan on public.ft1 t1
1975                Output: t1.c1
1976                Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
1977          ->  Foreign Scan on public.ft2 t2
1978                Output: t2.c2
1979                Remote SQL: SELECT c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
1980 (11 rows)
1981
1982 SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
1983  c1  
1984 -----
1985  110
1986  111
1987  112
1988  113
1989  114
1990  115
1991  116
1992  117
1993  118
1994  119
1995 (10 rows)
1996
1997 -- CROSS JOIN, not pushed down
1998 EXPLAIN (VERBOSE, COSTS OFF)
1999 SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
2000                              QUERY PLAN                              
2001 ---------------------------------------------------------------------
2002  Limit
2003    Output: t1.c1, t2.c1
2004    ->  Sort
2005          Output: t1.c1, t2.c1
2006          Sort Key: t1.c1, t2.c1
2007          ->  Nested Loop
2008                Output: t1.c1, t2.c1
2009                ->  Foreign Scan on public.ft1 t1
2010                      Output: t1.c1
2011                      Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2012                ->  Materialize
2013                      Output: t2.c1
2014                      ->  Foreign Scan on public.ft2 t2
2015                            Output: t2.c1
2016                            Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2017 (15 rows)
2018
2019 SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
2020  c1 | c1  
2021 ----+-----
2022   1 | 101
2023   1 | 102
2024   1 | 103
2025   1 | 104
2026   1 | 105
2027   1 | 106
2028   1 | 107
2029   1 | 108
2030   1 | 109
2031   1 | 110
2032 (10 rows)
2033
2034 -- different server, not pushed down. No result expected.
2035 EXPLAIN (VERBOSE, COSTS OFF)
2036 SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
2037                                       QUERY PLAN                                       
2038 ---------------------------------------------------------------------------------------
2039  Limit
2040    Output: t1.c1, t2.c1
2041    ->  Merge Join
2042          Output: t1.c1, t2.c1
2043          Merge Cond: (t2.c1 = t1.c1)
2044          ->  Foreign Scan on public.ft6 t2
2045                Output: t2.c1, t2.c2, t2.c3
2046                Remote SQL: SELECT c1 FROM "S 1"."T 4" ORDER BY c1 ASC NULLS LAST
2047          ->  Materialize
2048                Output: t1.c1, t1.c2, t1.c3
2049                ->  Foreign Scan on public.ft5 t1
2050                      Output: t1.c1, t1.c2, t1.c3
2051                      Remote SQL: SELECT c1 FROM "S 1"."T 4" ORDER BY c1 ASC NULLS LAST
2052 (13 rows)
2053
2054 SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
2055  c1 | c1 
2056 ----+----
2057 (0 rows)
2058
2059 -- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS
2060 -- JOIN since c8 in both tables has same value.
2061 EXPLAIN (VERBOSE, COSTS OFF)
2062 SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
2063                                QUERY PLAN                                
2064 -------------------------------------------------------------------------
2065  Limit
2066    Output: t1.c1, t2.c1
2067    ->  Sort
2068          Output: t1.c1, t2.c1
2069          Sort Key: t1.c1, t2.c1
2070          ->  Merge Left Join
2071                Output: t1.c1, t2.c1
2072                Merge Cond: (t1.c8 = t2.c8)
2073                ->  Sort
2074                      Output: t1.c1, t1.c8
2075                      Sort Key: t1.c8
2076                      ->  Foreign Scan on public.ft1 t1
2077                            Output: t1.c1, t1.c8
2078                            Remote SQL: SELECT "C 1", c8 FROM "S 1"."T 1"
2079                ->  Sort
2080                      Output: t2.c1, t2.c8
2081                      Sort Key: t2.c8
2082                      ->  Foreign Scan on public.ft2 t2
2083                            Output: t2.c1, t2.c8
2084                            Remote SQL: SELECT "C 1", c8 FROM "S 1"."T 1"
2085 (20 rows)
2086
2087 SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
2088  c1 | c1  
2089 ----+-----
2090   1 | 101
2091   1 | 102
2092   1 | 103
2093   1 | 104
2094   1 | 105
2095   1 | 106
2096   1 | 107
2097   1 | 108
2098   1 | 109
2099   1 | 110
2100 (10 rows)
2101
2102 -- unsafe conditions on one side (c8 has a UDT), not pushed down.
2103 EXPLAIN (VERBOSE, COSTS OFF)
2104 SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
2105                                  QUERY PLAN                                  
2106 -----------------------------------------------------------------------------
2107  Limit
2108    Output: t1.c1, t2.c1, t1.c3
2109    ->  Sort
2110          Output: t1.c1, t2.c1, t1.c3
2111          Sort Key: t1.c3, t1.c1
2112          ->  Hash Right Join
2113                Output: t1.c1, t2.c1, t1.c3
2114                Hash Cond: (t2.c1 = t1.c1)
2115                ->  Foreign Scan on public.ft2 t2
2116                      Output: t2.c1
2117                      Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2118                ->  Hash
2119                      Output: t1.c1, t1.c3
2120                      ->  Foreign Scan on public.ft1 t1
2121                            Output: t1.c1, t1.c3
2122                            Filter: (t1.c8 = 'foo'::user_enum)
2123                            Remote SQL: SELECT "C 1", c3, c8 FROM "S 1"."T 1"
2124 (17 rows)
2125
2126 SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
2127  c1  | c1  
2128 -----+-----
2129  101 | 101
2130  102 | 102
2131  103 | 103
2132  104 | 104
2133  105 | 105
2134  106 | 106
2135  107 | 107
2136  108 | 108
2137  109 | 109
2138  110 | 110
2139 (10 rows)
2140
2141 -- join where unsafe to pushdown condition in WHERE clause has a column not
2142 -- in the SELECT clause. In this test unsafe clause needs to have column
2143 -- references from both joining sides so that the clause is not pushed down
2144 -- into one of the joining sides.
2145 EXPLAIN (VERBOSE, COSTS OFF)
2146 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
2147                                                                       QUERY PLAN                                                                       
2148 -------------------------------------------------------------------------------------------------------------------------------------------------------
2149  Limit
2150    Output: t1.c1, t2.c1, t1.c3
2151    ->  Sort
2152          Output: t1.c1, t2.c1, t1.c3
2153          Sort Key: t1.c3, t1.c1
2154          ->  Foreign Scan
2155                Output: t1.c1, t2.c1, t1.c3
2156                Filter: (t1.c8 = t2.c8)
2157                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2158                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"))))
2159 (10 rows)
2160
2161 SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
2162  c1  | c1  
2163 -----+-----
2164  101 | 101
2165  102 | 102
2166  103 | 103
2167  104 | 104
2168  105 | 105
2169  106 | 106
2170  107 | 107
2171  108 | 108
2172  109 | 109
2173  110 | 110
2174 (10 rows)
2175
2176 -- Aggregate after UNION, for testing setrefs
2177 EXPLAIN (VERBOSE, COSTS OFF)
2178 SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10;
2179                                                                      QUERY PLAN                                                                     
2180 ----------------------------------------------------------------------------------------------------------------------------------------------------
2181  Limit
2182    Output: t1.c1, (avg((t1.c1 + t2.c1)))
2183    ->  Sort
2184          Output: t1.c1, (avg((t1.c1 + t2.c1)))
2185          Sort Key: t1.c1
2186          ->  HashAggregate
2187                Output: t1.c1, avg((t1.c1 + t2.c1))
2188                Group Key: t1.c1
2189                ->  HashAggregate
2190                      Output: t1.c1, t2.c1
2191                      Group Key: t1.c1, t2.c1
2192                      ->  Append
2193                            ->  Foreign Scan
2194                                  Output: t1.c1, t2.c1
2195                                  Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2196                                  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"))))
2197                            ->  Foreign Scan
2198                                  Output: t1_1.c1, t2_1.c1
2199                                  Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2200                                  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"))))
2201 (20 rows)
2202
2203 SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10;
2204  t1c1 |         avg          
2205 ------+----------------------
2206   101 | 202.0000000000000000
2207   102 | 204.0000000000000000
2208   103 | 206.0000000000000000
2209   104 | 208.0000000000000000
2210   105 | 210.0000000000000000
2211   106 | 212.0000000000000000
2212   107 | 214.0000000000000000
2213   108 | 216.0000000000000000
2214   109 | 218.0000000000000000
2215   110 | 220.0000000000000000
2216 (10 rows)
2217
2218 -- join with lateral reference
2219 EXPLAIN (VERBOSE, COSTS OFF)
2220 SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10;
2221                                                                              QUERY PLAN                                                                             
2222 --------------------------------------------------------------------------------------------------------------------------------------------------------------------
2223  Limit
2224    Output: t1."C 1"
2225    ->  Nested Loop
2226          Output: t1."C 1"
2227          ->  Index Scan using t1_pkey on "S 1"."T 1" t1
2228                Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
2229          ->  HashAggregate
2230                Output: t2.c1, t3.c1
2231                Group Key: t2.c1, t3.c1
2232                ->  Foreign Scan
2233                      Output: t2.c1, t3.c1
2234                      Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
2235                      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))))
2236 (13 rows)
2237
2238 SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10;
2239  C 1 
2240 -----
2241    1
2242    1
2243    1
2244    1
2245    1
2246    1
2247    1
2248    1
2249    1
2250    1
2251 (10 rows)
2252
2253 -- non-Var items in targetlist of the nullable rel of a join preventing
2254 -- push-down in some cases
2255 -- unable to push {ft1, ft2}
2256 EXPLAIN (VERBOSE, COSTS OFF)
2257 SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15;
2258                                                         QUERY PLAN                                                         
2259 ---------------------------------------------------------------------------------------------------------------------------
2260  Nested Loop Left Join
2261    Output: (13), ft2.c1
2262    Join Filter: (13 = ft2.c1)
2263    ->  Foreign Scan on public.ft2
2264          Output: ft2.c1
2265          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
2266    ->  Materialize
2267          Output: (13)
2268          ->  Foreign Scan on public.ft1
2269                Output: 13
2270                Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE (("C 1" = 13))
2271 (11 rows)
2272
2273 SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15;
2274  a  | c1 
2275 ----+----
2276     | 10
2277     | 11
2278     | 12
2279  13 | 13
2280     | 14
2281     | 15
2282 (6 rows)
2283
2284 -- ok to push {ft1, ft2} but not {ft1, ft2, ft4}
2285 EXPLAIN (VERBOSE, COSTS OFF)
2286 SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15;
2287                                                                                     QUERY PLAN                                                                                     
2288 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2289  Nested Loop Left Join
2290    Output: ft4.c1, (13), ft1.c1, ft2.c1
2291    Join Filter: (ft4.c1 = ft1.c1)
2292    ->  Foreign Scan on public.ft4
2293          Output: ft4.c1, ft4.c2, ft4.c3
2294          Remote SQL: SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 10)) AND ((c1 <= 15))
2295    ->  Materialize
2296          Output: ft1.c1, ft2.c1, (13)
2297          ->  Foreign Scan
2298                Output: ft1.c1, ft2.c1, 13
2299                Relations: (public.ft1) INNER JOIN (public.ft2)
2300                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
2301 (12 rows)
2302
2303 SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15;
2304  c1 | a  | b  | c  
2305 ----+----+----+----
2306  10 |    |    |   
2307  12 | 13 | 12 | 12
2308  14 |    |    |   
2309 (3 rows)
2310
2311 -- join with nullable side with some columns with null values
2312 UPDATE ft5 SET c3 = null where c1 % 9 = 0;
2313 EXPLAIN (VERBOSE, COSTS OFF)
2314 SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1;
2315                                                                                                                                 QUERY PLAN                                                                                                                                 
2316 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2317  Foreign Scan
2318    Output: ft5.*, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2
2319    Relations: (public.ft5) INNER JOIN (public.ft4)
2320    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
2321 (4 rows)
2322
2323 SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1;
2324       ft5       | c1 | c2 |   c3   | c1 | c2 
2325 ----------------+----+----+--------+----+----
2326  (12,13,AAA012) | 12 | 13 | AAA012 | 12 | 13
2327  (18,19,)       | 18 | 19 |        | 18 | 19
2328  (24,25,AAA024) | 24 | 25 | AAA024 | 24 | 25
2329  (30,31,AAA030) | 30 | 31 | AAA030 | 30 | 31
2330 (4 rows)
2331
2332 -- multi-way join involving multiple merge joins
2333 -- (this case used to have EPQ-related planning problems)
2334 SET enable_nestloop TO false;
2335 SET enable_hashjoin TO false;
2336 EXPLAIN (VERBOSE, COSTS OFF)
2337 SELECT * FROM ft1, ft2, ft4, ft5 WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1
2338     AND ft1.c2 = ft5.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE;
2339                                                                                                                                                                                                                                                                                                                                                                                                                              QUERY PLAN                                                                                                                                                                                                                                                                                                                                                                                                                             
2340 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2341  LockRows
2342    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.*
2343    ->  Foreign Scan
2344          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.*
2345          Relations: (((public.ft1) INNER JOIN (public.ft2)) INNER JOIN (public.ft4)) INNER JOIN (public.ft5)
2346          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
2347          ->  Merge Join
2348                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.*
2349                Merge Cond: (ft1.c2 = ft5.c1)
2350                ->  Merge Join
2351                      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.*
2352                      Merge Cond: (ft1.c2 = ft4.c1)
2353                      ->  Sort
2354                            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.*
2355                            Sort Key: ft1.c2
2356                            ->  Merge Join
2357                                  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.*
2358                                  Merge Cond: (ft1.c1 = ft2.c1)
2359                                  ->  Sort
2360                                        Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2361                                        Sort Key: ft1.c1
2362                                        ->  Foreign Scan on public.ft1
2363                                              Output: ft1.c1, ft1.c2, ft1.c3, ft1.c4, ft1.c5, ft1.c6, ft1.c7, ft1.c8, ft1.*
2364                                              Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 100)) FOR UPDATE
2365                                  ->  Materialize
2366                                        Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*
2367                                        ->  Foreign Scan on public.ft2
2368                                              Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.*
2369                                              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
2370                      ->  Sort
2371                            Output: ft4.c1, ft4.c2, ft4.c3, ft4.*
2372                            Sort Key: ft4.c1
2373                            ->  Foreign Scan on public.ft4
2374                                  Output: ft4.c1, ft4.c2, ft4.c3, ft4.*
2375                                  Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3" FOR UPDATE
2376                ->  Sort
2377                      Output: ft5.c1, ft5.c2, ft5.c3, ft5.*
2378                      Sort Key: ft5.c1
2379                      ->  Foreign Scan on public.ft5
2380                            Output: ft5.c1, ft5.c2, ft5.c3, ft5.*
2381                            Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4" FOR UPDATE
2382 (41 rows)
2383
2384 SELECT * FROM ft1, ft2, ft4, ft5 WHERE ft1.c1 = ft2.c1 AND ft1.c2 = ft4.c1
2385     AND ft1.c2 = ft5.c1 AND ft1.c1 < 100 AND ft2.c1 < 100 FOR UPDATE;
2386  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1 | c2 |   c3   | c1 | c2 |   c3   
2387 ----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+--------+----+----+--------
2388   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
2389  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
2390  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
2391  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
2392  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
2393  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
2394  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
2395  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
2396  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
2397  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
2398 (10 rows)
2399
2400 RESET enable_nestloop;
2401 RESET enable_hashjoin;
2402 -- check join pushdown in situations where multiple userids are involved
2403 CREATE ROLE regress_view_owner SUPERUSER;
2404 CREATE USER MAPPING FOR regress_view_owner SERVER loopback;
2405 GRANT SELECT ON ft4 TO regress_view_owner;
2406 GRANT SELECT ON ft5 TO regress_view_owner;
2407 CREATE VIEW v4 AS SELECT * FROM ft4;
2408 CREATE VIEW v5 AS SELECT * FROM ft5;
2409 ALTER VIEW v5 OWNER TO regress_view_owner;
2410 EXPLAIN (VERBOSE, COSTS OFF)
2411 SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;  -- can't be pushed down, different view owners
2412                               QUERY PLAN                              
2413 ----------------------------------------------------------------------
2414  Limit
2415    Output: ft4.c1, ft5.c2, ft5.c1
2416    ->  Sort
2417          Output: ft4.c1, ft5.c2, ft5.c1
2418          Sort Key: ft4.c1, ft5.c1
2419          ->  Hash Left Join
2420                Output: ft4.c1, ft5.c2, ft5.c1
2421                Hash Cond: (ft4.c1 = ft5.c1)
2422                ->  Foreign Scan on public.ft4
2423                      Output: ft4.c1, ft4.c2, ft4.c3
2424                      Remote SQL: SELECT c1 FROM "S 1"."T 3"
2425                ->  Hash
2426                      Output: ft5.c2, ft5.c1
2427                      ->  Foreign Scan on public.ft5
2428                            Output: ft5.c2, ft5.c1
2429                            Remote SQL: SELECT c1, c2 FROM "S 1"."T 4"
2430 (16 rows)
2431
2432 SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
2433  c1 | c2 
2434 ----+----
2435  22 |   
2436  24 | 25
2437  26 |   
2438  28 |   
2439  30 | 31
2440  32 |   
2441  34 |   
2442  36 | 37
2443  38 |   
2444  40 |   
2445 (10 rows)
2446
2447 ALTER VIEW v4 OWNER TO regress_view_owner;
2448 EXPLAIN (VERBOSE, COSTS OFF)
2449 SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;  -- can be pushed down
2450                                                                                 QUERY PLAN                                                                                
2451 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2452  Limit
2453    Output: ft4.c1, ft5.c2, ft5.c1
2454    ->  Foreign Scan
2455          Output: ft4.c1, ft5.c2, ft5.c1
2456          Relations: (public.ft4) LEFT JOIN (public.ft5)
2457          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
2458 (6 rows)
2459
2460 SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
2461  c1 | c2 
2462 ----+----
2463  22 |   
2464  24 | 25
2465  26 |   
2466  28 |   
2467  30 | 31
2468  32 |   
2469  34 |   
2470  36 | 37
2471  38 |   
2472  40 |   
2473 (10 rows)
2474
2475 EXPLAIN (VERBOSE, COSTS OFF)
2476 SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;  -- can't be pushed down, view owner not current user
2477                               QUERY PLAN                              
2478 ----------------------------------------------------------------------
2479  Limit
2480    Output: ft4.c1, t2.c2, t2.c1
2481    ->  Sort
2482          Output: ft4.c1, t2.c2, t2.c1
2483          Sort Key: ft4.c1, t2.c1
2484          ->  Hash Left Join
2485                Output: ft4.c1, t2.c2, t2.c1
2486                Hash Cond: (ft4.c1 = t2.c1)
2487                ->  Foreign Scan on public.ft4
2488                      Output: ft4.c1, ft4.c2, ft4.c3
2489                      Remote SQL: SELECT c1 FROM "S 1"."T 3"
2490                ->  Hash
2491                      Output: t2.c2, t2.c1
2492                      ->  Foreign Scan on public.ft5 t2
2493                            Output: t2.c2, t2.c1
2494                            Remote SQL: SELECT c1, c2 FROM "S 1"."T 4"
2495 (16 rows)
2496
2497 SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
2498  c1 | c2 
2499 ----+----
2500  22 |   
2501  24 | 25
2502  26 |   
2503  28 |   
2504  30 | 31
2505  32 |   
2506  34 |   
2507  36 | 37
2508  38 |   
2509  40 |   
2510 (10 rows)
2511
2512 ALTER VIEW v4 OWNER TO CURRENT_USER;
2513 EXPLAIN (VERBOSE, COSTS OFF)
2514 SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;  -- can be pushed down
2515                                                                                 QUERY PLAN                                                                                
2516 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2517  Limit
2518    Output: ft4.c1, t2.c2, t2.c1
2519    ->  Foreign Scan
2520          Output: ft4.c1, t2.c2, t2.c1
2521          Relations: (public.ft4) LEFT JOIN (public.ft5 t2)
2522          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
2523 (6 rows)
2524
2525 SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
2526  c1 | c2 
2527 ----+----
2528  22 |   
2529  24 | 25
2530  26 |   
2531  28 |   
2532  30 | 31
2533  32 |   
2534  34 |   
2535  36 | 37
2536  38 |   
2537  40 |   
2538 (10 rows)
2539
2540 ALTER VIEW v4 OWNER TO regress_view_owner;
2541 -- cleanup
2542 DROP OWNED BY regress_view_owner;
2543 DROP ROLE regress_view_owner;
2544 -- ===================================================================
2545 -- Aggregate and grouping queries
2546 -- ===================================================================
2547 -- Simple aggregates
2548 explain (verbose, costs off)
2549 select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2;
2550                                                                       QUERY PLAN                                                                      
2551 ------------------------------------------------------------------------------------------------------------------------------------------------------
2552  Result
2553    Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2
2554    ->  Sort
2555          Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2
2556          Sort Key: (count(ft1.c6)), (sum(ft1.c1))
2557          ->  Foreign Scan
2558                Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2
2559                Relations: Aggregate on (public.ft1)
2560                Remote SQL: SELECT count(c6), sum("C 1"), avg("C 1"), min(c2), max("C 1"), stddev(c2), c2 FROM "S 1"."T 1" WHERE ((c2 < 5)) GROUP BY 7
2561 (9 rows)
2562
2563 select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2;
2564  count |  sum  |         avg          | min | max  | stddev | sum2  
2565 -------+-------+----------------------+-----+------+--------+-------
2566    100 | 49600 | 496.0000000000000000 |   1 |  991 |      0 | 49600
2567    100 | 49700 | 497.0000000000000000 |   2 |  992 |      0 | 49700
2568    100 | 49800 | 498.0000000000000000 |   3 |  993 |      0 | 49800
2569    100 | 49900 | 499.0000000000000000 |   4 |  994 |      0 | 49900
2570    100 | 50500 | 505.0000000000000000 |   0 | 1000 |      0 | 50500
2571 (5 rows)
2572
2573 -- Aggregate is not pushed down as aggregation contains random()
2574 explain (verbose, costs off)
2575 select sum(c1 * (random() <= 1)::int) as sum, avg(c1) from ft1;
2576                                   QUERY PLAN                                   
2577 -------------------------------------------------------------------------------
2578  Aggregate
2579    Output: sum((c1 * ((random() <= '1'::double precision))::integer)), avg(c1)
2580    ->  Foreign Scan on public.ft1
2581          Output: c1
2582          Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
2583 (5 rows)
2584
2585 -- Aggregate over join query
2586 explain (verbose, costs off)
2587 select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6;
2588                                                                     QUERY PLAN                                                                    
2589 --------------------------------------------------------------------------------------------------------------------------------------------------
2590  Foreign Scan
2591    Output: (count(*)), (sum(t1.c1)), (avg(t2.c1))
2592    Relations: Aggregate on ((public.ft1 t1) INNER JOIN (public.ft1 t2))
2593    Remote SQL: SELECT count(*), sum(r1."C 1"), avg(r2."C 1") FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r2.c2 = 6)) AND ((r1.c2 = 6))))
2594 (4 rows)
2595
2596 select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6;
2597  count |   sum   |         avg          
2598 -------+---------+----------------------
2599  10000 | 5010000 | 501.0000000000000000
2600 (1 row)
2601
2602 -- Not pushed down due to local conditions present in underneath input rel
2603 explain (verbose, costs off)
2604 select sum(t1.c1), count(t2.c1) from ft1 t1 inner join ft2 t2 on (t1.c1 = t2.c1) where ((t1.c1 * t2.c1)/(t1.c1 * t2.c1)) * random() <= 1;
2605                                                          QUERY PLAN                                                         
2606 ----------------------------------------------------------------------------------------------------------------------------
2607  Aggregate
2608    Output: sum(t1.c1), count(t2.c1)
2609    ->  Foreign Scan
2610          Output: t1.c1, t2.c1
2611          Filter: (((((t1.c1 * t2.c1) / (t1.c1 * t2.c1)))::double precision * random()) <= '1'::double precision)
2612          Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
2613          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"))))
2614 (7 rows)
2615
2616 -- GROUP BY clause having expressions
2617 explain (verbose, costs off)
2618 select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
2619                                       QUERY PLAN                                       
2620 ---------------------------------------------------------------------------------------
2621  Sort
2622    Output: ((c2 / 2)), ((sum(c2) * (c2 / 2)))
2623    Sort Key: ((ft1.c2 / 2))
2624    ->  Foreign Scan
2625          Output: ((c2 / 2)), ((sum(c2) * (c2 / 2)))
2626          Relations: Aggregate on (public.ft1)
2627          Remote SQL: SELECT (c2 / 2), (sum(c2) * (c2 / 2)) FROM "S 1"."T 1" GROUP BY 1
2628 (7 rows)
2629
2630 select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
2631  ?column? | ?column? 
2632 ----------+----------
2633         0 |        0
2634         1 |      500
2635         2 |     1800
2636         3 |     3900
2637         4 |     6800
2638 (5 rows)
2639
2640 -- Aggregates in subquery are pushed down.
2641 explain (verbose, costs off)
2642 select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x;
2643                                          QUERY PLAN                                          
2644 ---------------------------------------------------------------------------------------------
2645  Aggregate
2646    Output: count(ft1.c2), sum(ft1.c2)
2647    ->  Sort
2648          Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision))
2649          Sort Key: ft1.c2, (sum(ft1.c1))
2650          ->  Foreign Scan
2651                Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision))
2652                Relations: Aggregate on (public.ft1)
2653                Remote SQL: SELECT c2, sum("C 1"), sqrt("C 1") FROM "S 1"."T 1" GROUP BY 1, 3
2654 (9 rows)
2655
2656 select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x;
2657  count | sum  
2658 -------+------
2659   1000 | 4500
2660 (1 row)
2661
2662 -- Aggregate is still pushed down by taking unshippable expression out
2663 explain (verbose, costs off)
2664 select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2;
2665                                             QUERY PLAN                                             
2666 ---------------------------------------------------------------------------------------------------
2667  Sort
2668    Output: ((c2 * ((random() <= '1'::double precision))::integer)), ((sum(c1) * c2)), c2
2669    Sort Key: ((ft1.c2 * ((random() <= '1'::double precision))::integer)), ((sum(ft1.c1) * ft1.c2))
2670    ->  Foreign Scan
2671          Output: (c2 * ((random() <= '1'::double precision))::integer), ((sum(c1) * c2)), c2
2672          Relations: Aggregate on (public.ft1)
2673          Remote SQL: SELECT (sum("C 1") * c2), c2 FROM "S 1"."T 1" GROUP BY 2
2674 (7 rows)
2675
2676 select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2;
2677  sum1 |  sum2  
2678 ------+--------
2679     0 |      0
2680     1 |  49600
2681     2 |  99400
2682     3 | 149400
2683     4 | 199600
2684     5 | 250000
2685     6 | 300600
2686     7 | 351400
2687     8 | 402400
2688     9 | 453600
2689 (10 rows)
2690
2691 -- Aggregate with unshippable GROUP BY clause are not pushed
2692 explain (verbose, costs off)
2693 select c2 * (random() <= 1)::int as c2 from ft2 group by c2 * (random() <= 1)::int order by 1;
2694                                   QUERY PLAN                                  
2695 ------------------------------------------------------------------------------
2696  Sort
2697    Output: ((c2 * ((random() <= '1'::double precision))::integer))
2698    Sort Key: ((ft2.c2 * ((random() <= '1'::double precision))::integer))
2699    ->  HashAggregate
2700          Output: ((c2 * ((random() <= '1'::double precision))::integer))
2701          Group Key: (ft2.c2 * ((random() <= '1'::double precision))::integer)
2702          ->  Foreign Scan on public.ft2
2703                Output: (c2 * ((random() <= '1'::double precision))::integer)
2704                Remote SQL: SELECT c2 FROM "S 1"."T 1"
2705 (9 rows)
2706
2707 -- GROUP BY clause in various forms, cardinal, alias and constant expression
2708 explain (verbose, costs off)
2709 select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2;
2710                                       QUERY PLAN                                       
2711 ---------------------------------------------------------------------------------------
2712  Sort
2713    Output: (count(c2)), c2, 5, 7.0, 9
2714    Sort Key: ft1.c2
2715    ->  Foreign Scan
2716          Output: (count(c2)), c2, 5, 7.0, 9
2717          Relations: Aggregate on (public.ft1)
2718          Remote SQL: SELECT count(c2), c2, 5, 7.0, 9 FROM "S 1"."T 1" GROUP BY 2, 3, 5
2719 (7 rows)
2720
2721 select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2;
2722   w  | x | y |  z  
2723 -----+---+---+-----
2724  100 | 0 | 5 | 7.0
2725  100 | 1 | 5 | 7.0
2726  100 | 2 | 5 | 7.0
2727  100 | 3 | 5 | 7.0
2728  100 | 4 | 5 | 7.0
2729  100 | 5 | 5 | 7.0
2730  100 | 6 | 5 | 7.0
2731  100 | 7 | 5 | 7.0
2732  100 | 8 | 5 | 7.0
2733  100 | 9 | 5 | 7.0
2734 (10 rows)
2735
2736 -- GROUP BY clause referring to same column multiple times
2737 -- Also, ORDER BY contains an aggregate function
2738 explain (verbose, costs off)
2739 select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1);
2740                                           QUERY PLAN                                           
2741 -----------------------------------------------------------------------------------------------
2742  Sort
2743    Output: c2, c2, (sum(c1))
2744    Sort Key: (sum(ft1.c1))
2745    ->  Foreign Scan
2746          Output: c2, c2, (sum(c1))
2747          Relations: Aggregate on (public.ft1)
2748          Remote SQL: SELECT c2, c2, sum("C 1") FROM "S 1"."T 1" WHERE ((c2 > 6)) GROUP BY 1, 2
2749 (7 rows)
2750
2751 select c2, c2 from ft1 where c2 > 6 group by 1, 2 order by sum(c1);
2752  c2 | c2 
2753 ----+----
2754   7 |  7
2755   8 |  8
2756   9 |  9
2757 (3 rows)
2758
2759 -- Testing HAVING clause shippability
2760 explain (verbose, costs off)
2761 select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
2762                                                               QUERY PLAN                                                               
2763 ---------------------------------------------------------------------------------------------------------------------------------------
2764  Sort
2765    Output: c2, (sum(c1))
2766    Sort Key: ft2.c2
2767    ->  Foreign Scan
2768          Output: c2, (sum(c1))
2769          Relations: Aggregate on (public.ft2)
2770          Remote SQL: SELECT c2, sum("C 1") FROM "S 1"."T 1" GROUP BY 1 HAVING ((avg("C 1") < 500::numeric)) AND ((sum("C 1") < 49800))
2771 (7 rows)
2772
2773 select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
2774  c2 |  sum  
2775 ----+-------
2776   1 | 49600
2777   2 | 49700
2778 (2 rows)
2779
2780 -- Unshippable HAVING clause will be evaluated locally, and other qual in HAVING clause is pushed down
2781 explain (verbose, costs off)
2782 select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x;
2783                                                               QUERY PLAN                                                               
2784 ---------------------------------------------------------------------------------------------------------------------------------------
2785  Aggregate
2786    Output: count(*)
2787    ->  Foreign Scan
2788          Output: ft1.c5, NULL::bigint, (sqrt((ft1.c2)::double precision))
2789          Filter: (((((avg(ft1.c1)) / (avg(ft1.c1))))::double precision * random()) <= '1'::double precision)
2790          Relations: Aggregate on (public.ft1)
2791          Remote SQL: SELECT c5, NULL::bigint, sqrt(c2), avg("C 1") FROM "S 1"."T 1" GROUP BY 1, 3 HAVING ((avg("C 1") < 500::numeric))
2792 (7 rows)
2793
2794 select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x;
2795  count 
2796 -------
2797     49
2798 (1 row)
2799
2800 -- Aggregate in HAVING clause is not pushable, and thus aggregation is not pushed down
2801 explain (verbose, costs off)
2802 select sum(c1) from ft1 group by c2 having avg(c1 * (random() <= 1)::int) > 100 order by 1;
2803                                             QUERY PLAN                                             
2804 ---------------------------------------------------------------------------------------------------
2805  Sort
2806    Output: (sum(c1)), c2
2807    Sort Key: (sum(ft1.c1))
2808    ->  HashAggregate
2809          Output: sum(c1), c2
2810          Group Key: ft1.c2
2811          Filter: (avg((ft1.c1 * ((random() <= '1'::double precision))::integer)) > '100'::numeric)
2812          ->  Foreign Scan on public.ft1
2813                Output: c2, c1
2814                Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1"
2815 (10 rows)
2816
2817 -- Testing ORDER BY, DISTINCT, FILTER, Ordered-sets and VARIADIC within aggregates
2818 -- ORDER BY within aggregate, same column used to order
2819 explain (verbose, costs off)
2820 select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1;
2821                                                            QUERY PLAN                                                            
2822 ---------------------------------------------------------------------------------------------------------------------------------
2823  Sort
2824    Output: (array_agg(c1 ORDER BY c1)), c2
2825    Sort Key: (array_agg(ft1.c1 ORDER BY ft1.c1))
2826    ->  Foreign Scan
2827          Output: (array_agg(c1 ORDER BY c1)), c2
2828          Relations: Aggregate on (public.ft1)
2829          Remote SQL: SELECT array_agg("C 1" ORDER BY "C 1" ASC NULLS LAST), c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) GROUP BY 2
2830 (7 rows)
2831
2832 select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1;
2833            array_agg            
2834 --------------------------------
2835  {1,11,21,31,41,51,61,71,81,91}
2836  {2,12,22,32,42,52,62,72,82,92}
2837  {3,13,23,33,43,53,63,73,83,93}
2838  {4,14,24,34,44,54,64,74,84,94}
2839  {5,15,25,35,45,55,65,75,85,95}
2840  {6,16,26,36,46,56,66,76,86,96}
2841  {7,17,27,37,47,57,67,77,87,97}
2842  {8,18,28,38,48,58,68,78,88,98}
2843  {9,19,29,39,49,59,69,79,89,99}
2844  {10,20,30,40,50,60,70,80,90}
2845 (10 rows)
2846
2847 -- ORDER BY within aggregate, different column used to order also using DESC
2848 explain (verbose, costs off)
2849 select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50;
2850                                                        QUERY PLAN                                                        
2851 -------------------------------------------------------------------------------------------------------------------------
2852  Foreign Scan
2853    Output: (array_agg(c5 ORDER BY c1 DESC))
2854    Relations: Aggregate on (public.ft2)
2855    Remote SQL: SELECT array_agg(c5 ORDER BY "C 1" DESC NULLS FIRST) FROM "S 1"."T 1" WHERE (("C 1" < 50)) AND ((c2 = 6))
2856 (4 rows)
2857
2858 select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50;
2859                                                                 array_agg                                                                 
2860 ------------------------------------------------------------------------------------------------------------------------------------------
2861  {"Mon Feb 16 00:00:00 1970","Fri Feb 06 00:00:00 1970","Tue Jan 27 00:00:00 1970","Sat Jan 17 00:00:00 1970","Wed Jan 07 00:00:00 1970"}
2862 (1 row)
2863
2864 -- DISTINCT within aggregate
2865 explain (verbose, costs off)
2866 select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
2867                                                                                                       QUERY PLAN                                                                                                      
2868 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2869  Sort
2870    Output: (array_agg(DISTINCT (t1.c1 % 5))), ((t2.c1 % 3))
2871    Sort Key: (array_agg(DISTINCT (t1.c1 % 5)))
2872    ->  Foreign Scan
2873          Output: (array_agg(DISTINCT (t1.c1 % 5))), ((t2.c1 % 3))
2874          Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
2875          Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5)), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2
2876 (7 rows)
2877
2878 select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
2879   array_agg   
2880 --------------
2881  {0,1,2,3,4}
2882  {1,2,3,NULL}
2883 (2 rows)
2884
2885 -- DISTINCT combined with ORDER BY within aggregate
2886 explain (verbose, costs off)
2887 select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
2888                                                                                                                          QUERY PLAN                                                                                                                         
2889 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2890  Sort
2891    Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))), ((t2.c1 % 3))
2892    Sort Key: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5)))
2893    ->  Foreign Scan
2894          Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))), ((t2.c1 % 3))
2895          Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
2896          Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) ASC NULLS LAST), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2
2897 (7 rows)
2898
2899 select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
2900   array_agg   
2901 --------------
2902  {0,1,2,3,4}
2903  {1,2,3,NULL}
2904 (2 rows)
2905
2906 explain (verbose, costs off)
2907 select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
2908                                                                                                                          QUERY PLAN                                                                                                                          
2909 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2910  Sort
2911    Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)), ((t2.c1 % 3))
2912    Sort Key: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST))
2913    ->  Foreign Scan
2914          Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)), ((t2.c1 % 3))
2915          Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
2916          Remote SQL: SELECT array_agg(DISTINCT (r1.c1 % 5) ORDER BY ((r1.c1 % 5)) DESC NULLS LAST), (r2.c1 % 3) FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) WHERE (((r1.c1 < 20) OR ((r1.c1 IS NULL) AND (r2.c1 < 5)))) GROUP BY 2
2917 (7 rows)
2918
2919 select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
2920   array_agg   
2921 --------------
2922  {3,2,1,NULL}
2923  {4,3,2,1,0}
2924 (2 rows)
2925
2926 -- FILTER within aggregate
2927 explain (verbose, costs off)
2928 select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last;
2929                                                     QUERY PLAN                                                     
2930 -------------------------------------------------------------------------------------------------------------------
2931  Sort
2932    Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2
2933    Sort Key: (sum(ft1.c1) FILTER (WHERE ((ft1.c1 < 100) AND (ft1.c2 > 5))))
2934    ->  Foreign Scan
2935          Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2
2936          Relations: Aggregate on (public.ft1)
2937          Remote SQL: SELECT sum("C 1") FILTER (WHERE (("C 1" < 100) AND (c2 > 5))), c2 FROM "S 1"."T 1" GROUP BY 2
2938 (7 rows)
2939
2940 select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last;
2941  sum 
2942 -----
2943  510
2944  520
2945  530
2946  540
2947     
2948     
2949     
2950     
2951     
2952     
2953 (10 rows)
2954
2955 -- DISTINCT, ORDER BY and FILTER within aggregate
2956 explain (verbose, costs off)
2957 select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2;
2958                                                                                         QUERY PLAN                                                                                        
2959 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
2960  Foreign Scan
2961    Output: (sum((c1 % 3))), (sum(DISTINCT (c1 % 3) ORDER BY (c1 % 3)) FILTER (WHERE ((c1 % 3) < 2))), c2
2962    Relations: Aggregate on (public.ft1)
2963    Remote SQL: SELECT sum(("C 1" % 3)), sum(DISTINCT ("C 1" % 3) ORDER BY (("C 1" % 3)) ASC NULLS LAST) FILTER (WHERE (("C 1" % 3) < 2)), c2 FROM "S 1"."T 1" WHERE ((c2 = 6)) GROUP BY 3
2964 (4 rows)
2965
2966 select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2;
2967  sum | sum | c2 
2968 -----+-----+----
2969   99 |   1 |  6
2970 (1 row)
2971
2972 -- Outer query is aggregation query
2973 explain (verbose, costs off)
2974 select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1;
2975                                                           QUERY PLAN                                                          
2976 ------------------------------------------------------------------------------------------------------------------------------
2977  Unique
2978    Output: ((SubPlan 1))
2979    ->  Sort
2980          Output: ((SubPlan 1))
2981          Sort Key: ((SubPlan 1))
2982          ->  Foreign Scan
2983                Output: (SubPlan 1)
2984                Relations: Aggregate on (public.ft2 t2)
2985                Remote SQL: SELECT count(*) FILTER (WHERE ((c2 = 6) AND ("C 1" < 10))) FROM "S 1"."T 1" WHERE (((c2 % 6) = 0))
2986                SubPlan 1
2987                  ->  Foreign Scan on public.ft1 t1
2988                        Output: (count(*) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))))
2989                        Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE (("C 1" = 6))
2990 (13 rows)
2991
2992 select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1;
2993  count 
2994 -------
2995      1
2996 (1 row)
2997
2998 -- Inner query is aggregation query
2999 explain (verbose, costs off)
3000 select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1;
3001                                                                       QUERY PLAN                                                                      
3002 ------------------------------------------------------------------------------------------------------------------------------------------------------
3003  Unique
3004    Output: ((SubPlan 1))
3005    ->  Sort
3006          Output: ((SubPlan 1))
3007          Sort Key: ((SubPlan 1))
3008          ->  Foreign Scan on public.ft2 t2
3009                Output: (SubPlan 1)
3010                Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (((c2 % 6) = 0))
3011                SubPlan 1
3012                  ->  Foreign Scan
3013                        Output: (count(t1.c1) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))))
3014                        Relations: Aggregate on (public.ft1 t1)
3015                        Remote SQL: SELECT count("C 1") FILTER (WHERE (($1::integer = 6) AND ($2::integer < 10))) FROM "S 1"."T 1" WHERE (("C 1" = 6))
3016 (13 rows)
3017
3018 select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 where t2.c2 % 6 = 0 order by 1;
3019  count 
3020 -------
3021      0
3022      1
3023 (2 rows)
3024
3025 -- Aggregate not pushed down as FILTER condition is not pushable
3026 explain (verbose, costs off)
3027 select sum(c1) filter (where (c1 / c1) * random() <= 1) from ft1 group by c2 order by 1;
3028                                                        QUERY PLAN                                                       
3029 ------------------------------------------------------------------------------------------------------------------------
3030  Sort
3031    Output: (sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision))), c2
3032    Sort Key: (sum(ft1.c1) FILTER (WHERE ((((ft1.c1 / ft1.c1))::double precision * random()) <= '1'::double precision)))
3033    ->  HashAggregate
3034          Output: sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision)), c2
3035          Group Key: ft1.c2
3036          ->  Foreign Scan on public.ft1
3037                Output: c2, c1
3038                Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1"
3039 (9 rows)
3040
3041 explain (verbose, costs off)
3042 select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1;
3043                             QUERY PLAN                             
3044 -------------------------------------------------------------------
3045  Aggregate
3046    Output: sum(ft1.c2) FILTER (WHERE (hashed SubPlan 1))
3047    ->  Foreign Scan on public.ft1
3048          Output: ft1.c2
3049          Remote SQL: SELECT c2 FROM "S 1"."T 1"
3050    SubPlan 1
3051      ->  Foreign Scan on public.ft1 ft1_1
3052            Output: ft1_1.c2
3053            Remote SQL: SELECT c2 FROM "S 1"."T 1" WHERE ((c2 < 5))
3054 (9 rows)
3055
3056 -- Ordered-sets within aggregate
3057 explain (verbose, costs off)
3058 select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2;
3059                                                                                                                                                                            QUERY PLAN                                                                                                                                                                           
3060 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3061  Sort
3062    Output: c2, (rank('10'::character varying) WITHIN GROUP (ORDER BY c6)), (percentile_cont((((c2)::numeric / '10'::numeric))::double precision) WITHIN GROUP (ORDER BY ((c1)::double precision)))
3063    Sort Key: ft1.c2
3064    ->  Foreign Scan
3065          Output: c2, (rank('10'::character varying) WITHIN GROUP (ORDER BY c6)), (percentile_cont((((c2)::numeric / '10'::numeric))::double precision) WITHIN GROUP (ORDER BY ((c1)::double precision)))
3066          Relations: Aggregate on (public.ft1)
3067          Remote SQL: SELECT c2, rank('10'::character varying) WITHIN GROUP (ORDER BY c6 ASC NULLS LAST), percentile_cont((c2 / 10::numeric)) WITHIN GROUP (ORDER BY ("C 1") ASC NULLS LAST) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1 HAVING ((percentile_cont((c2 / 10::numeric)) WITHIN GROUP (ORDER BY ("C 1") ASC NULLS LAST) < 500::double precision))
3068 (7 rows)
3069
3070 select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2;
3071  c2 | rank | percentile_cont 
3072 ----+------+-----------------
3073   0 |  101 |              10
3074   1 |  101 |             100
3075   2 |    1 |             200
3076   3 |    1 |             300
3077   4 |    1 |             400
3078 (5 rows)
3079
3080 -- Using multiple arguments within aggregates
3081 explain (verbose, costs off)
3082 select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1;
3083                                                                              QUERY PLAN                                                                             
3084 --------------------------------------------------------------------------------------------------------------------------------------------------------------------
3085  Foreign Scan
3086    Output: c1, (rank(c1, c2) WITHIN GROUP (ORDER BY c1, c2)), c2
3087    Relations: Aggregate on (public.ft1)
3088    Remote SQL: SELECT "C 1", rank("C 1", c2) WITHIN GROUP (ORDER BY "C 1" ASC NULLS LAST, c2 ASC NULLS LAST), c2 FROM "S 1"."T 1" WHERE (("C 1" = 6)) GROUP BY 1, 3
3089 (4 rows)
3090
3091 select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1;
3092  c1 | rank 
3093 ----+------
3094   6 |    1
3095 (1 row)
3096
3097 -- User defined function for user defined aggregate, VARIADIC
3098 create function least_accum(anyelement, variadic anyarray)
3099 returns anyelement language sql as
3100   'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)';
3101 create aggregate least_agg(variadic items anyarray) (
3102   stype = anyelement, sfunc = least_accum
3103 );
3104 -- Disable hash aggregation for plan stability.
3105 set enable_hashagg to false;
3106 -- Not pushed down due to user defined aggregate
3107 explain (verbose, costs off)
3108 select c2, least_agg(c1) from ft1 group by c2 order by c2;
3109                                     QUERY PLAN                                    
3110 ----------------------------------------------------------------------------------
3111  GroupAggregate
3112    Output: c2, least_agg(VARIADIC ARRAY[c1])
3113    Group Key: ft1.c2
3114    ->  Foreign Scan on public.ft1
3115          Output: c2, c1
3116          Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
3117 (6 rows)
3118
3119 -- Add function and aggregate into extension
3120 alter extension postgres_fdw add function least_accum(anyelement, variadic anyarray);
3121 alter extension postgres_fdw add aggregate least_agg(variadic items anyarray);
3122 alter server loopback options (set extensions 'postgres_fdw');
3123 -- Now aggregate will be pushed.  Aggregate will display VARIADIC argument.
3124 explain (verbose, costs off)
3125 select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2;
3126                                                       QUERY PLAN                                                       
3127 -----------------------------------------------------------------------------------------------------------------------
3128  Sort
3129    Output: c2, (least_agg(VARIADIC ARRAY[c1]))
3130    Sort Key: ft1.c2
3131    ->  Foreign Scan
3132          Output: c2, (least_agg(VARIADIC ARRAY[c1]))
3133          Relations: Aggregate on (public.ft1)
3134          Remote SQL: SELECT c2, public.least_agg(VARIADIC ARRAY["C 1"]) FROM "S 1"."T 1" WHERE ((c2 < 100)) GROUP BY 1
3135 (7 rows)
3136
3137 select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2;
3138  c2 | least_agg 
3139 ----+-----------
3140   0 |        10
3141   1 |         1
3142   2 |         2
3143   3 |         3
3144   4 |         4
3145   5 |         5
3146   6 |         6
3147   7 |         7
3148   8 |         8
3149   9 |         9
3150 (10 rows)
3151
3152 -- Remove function and aggregate from extension
3153 alter extension postgres_fdw drop function least_accum(anyelement, variadic anyarray);
3154 alter extension postgres_fdw drop aggregate least_agg(variadic items anyarray);
3155 alter server loopback options (set extensions 'postgres_fdw');
3156 -- Not pushed down as we have dropped objects from extension.
3157 explain (verbose, costs off)
3158 select c2, least_agg(c1) from ft1 group by c2 order by c2;
3159                                     QUERY PLAN                                    
3160 ----------------------------------------------------------------------------------
3161  GroupAggregate
3162    Output: c2, least_agg(VARIADIC ARRAY[c1])
3163    Group Key: ft1.c2
3164    ->  Foreign Scan on public.ft1
3165          Output: c2, c1
3166          Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
3167 (6 rows)
3168
3169 -- Cleanup
3170 reset enable_hashagg;
3171 drop aggregate least_agg(variadic items anyarray);
3172 drop function least_accum(anyelement, variadic anyarray);
3173 -- Testing USING OPERATOR() in ORDER BY within aggregate.
3174 -- For this, we need user defined operators along with operator family and
3175 -- operator class.  Create those and then add them in extension.  Note that
3176 -- user defined objects are considered unshippable unless they are part of
3177 -- the extension.
3178 create operator public.<^ (
3179  leftarg = int4,
3180  rightarg = int4,
3181  procedure = int4eq
3182 );
3183 create operator public.=^ (
3184  leftarg = int4,
3185  rightarg = int4,
3186  procedure = int4lt
3187 );
3188 create operator public.>^ (
3189  leftarg = int4,
3190  rightarg = int4,
3191  procedure = int4gt
3192 );
3193 create operator family my_op_family using btree;
3194 create function my_op_cmp(a int, b int) returns int as
3195   $$begin return btint4cmp(a, b); end $$ language plpgsql;
3196 create operator class my_op_class for type int using btree family my_op_family as
3197  operator 1 public.<^,
3198  operator 3 public.=^,
3199  operator 5 public.>^,
3200  function 1 my_op_cmp(int, int);
3201 -- This will not be pushed as user defined sort operator is not part of the
3202 -- extension yet.
3203 explain (verbose, costs off)
3204 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3205                                          QUERY PLAN                                         
3206 --------------------------------------------------------------------------------------------
3207  GroupAggregate
3208    Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2
3209    Group Key: ft2.c2
3210    ->  Foreign Scan on public.ft2
3211          Output: c2, c1
3212          Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6))
3213 (6 rows)
3214
3215 -- Add into extension
3216 alter extension postgres_fdw add operator class my_op_class using btree;
3217 alter extension postgres_fdw add function my_op_cmp(a int, b int);
3218 alter extension postgres_fdw add operator family my_op_family using btree;
3219 alter extension postgres_fdw add operator public.<^(int, int);
3220 alter extension postgres_fdw add operator public.=^(int, int);
3221 alter extension postgres_fdw add operator public.>^(int, int);
3222 alter server loopback options (set extensions 'postgres_fdw');
3223 -- Now this will be pushed as sort operator is part of the extension.
3224 explain (verbose, costs off)
3225 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3226                                                                            QUERY PLAN                                                                           
3227 ----------------------------------------------------------------------------------------------------------------------------------------------------------------
3228  Foreign Scan
3229    Output: (array_agg(c1 ORDER BY c1 USING <^ NULLS LAST)), c2
3230    Relations: Aggregate on (public.ft2)
3231    Remote SQL: SELECT array_agg("C 1" ORDER BY "C 1" USING OPERATOR(public.<^) NULLS LAST), c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6)) GROUP BY 2
3232 (4 rows)
3233
3234 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3235            array_agg            
3236 --------------------------------
3237  {6,16,26,36,46,56,66,76,86,96}
3238 (1 row)
3239
3240 -- Remove from extension
3241 alter extension postgres_fdw drop operator class my_op_class using btree;
3242 alter extension postgres_fdw drop function my_op_cmp(a int, b int);
3243 alter extension postgres_fdw drop operator family my_op_family using btree;
3244 alter extension postgres_fdw drop operator public.<^(int, int);
3245 alter extension postgres_fdw drop operator public.=^(int, int);
3246 alter extension postgres_fdw drop operator public.>^(int, int);
3247 alter server loopback options (set extensions 'postgres_fdw');
3248 -- This will not be pushed as sort operator is now removed from the extension.
3249 explain (verbose, costs off)
3250 select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
3251                                          QUERY PLAN                                         
3252 --------------------------------------------------------------------------------------------
3253  GroupAggregate
3254    Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2
3255    Group Key: ft2.c2
3256    ->  Foreign Scan on public.ft2
3257          Output: c2, c1
3258          Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6))
3259 (6 rows)
3260
3261 -- Cleanup
3262 drop operator class my_op_class using btree;
3263 drop function my_op_cmp(a int, b int);
3264 drop operator family my_op_family using btree;
3265 drop operator public.>^(int, int);
3266 drop operator public.=^(int, int);
3267 drop operator public.<^(int, int);
3268 -- Input relation to aggregate push down hook is not safe to pushdown and thus
3269 -- the aggregate cannot be pushed down to foreign server.
3270 explain (verbose, costs off)
3271 select count(t1.c3) from ft2 t1 left join ft2 t2 on (t1.c1 = random() * t2.c2);
3272                                         QUERY PLAN                                         
3273 -------------------------------------------------------------------------------------------
3274  Aggregate
3275    Output: count(t1.c3)
3276    ->  Nested Loop Left Join
3277          Output: t1.c3
3278          Join Filter: ((t1.c1)::double precision = (random() * (t2.c2)::double precision))
3279          ->  Foreign Scan on public.ft2 t1
3280                Output: t1.c3, t1.c1
3281                Remote SQL: SELECT "C 1", c3 FROM "S 1"."T 1"
3282          ->  Materialize
3283                Output: t2.c2
3284                ->  Foreign Scan on public.ft2 t2
3285                      Output: t2.c2
3286                      Remote SQL: SELECT c2 FROM "S 1"."T 1"
3287 (13 rows)
3288
3289 -- Subquery in FROM clause having aggregate
3290 explain (verbose, costs off)
3291 select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2;
3292                                           QUERY PLAN                                           
3293 -----------------------------------------------------------------------------------------------
3294  Sort
3295    Output: (count(*)), x.b
3296    Sort Key: (count(*)), x.b
3297    ->  HashAggregate
3298          Output: count(*), x.b
3299          Group Key: x.b
3300          ->  Hash Join
3301                Output: x.b
3302                Inner Unique: true
3303                Hash Cond: (ft1.c2 = x.a)
3304                ->  Foreign Scan on public.ft1
3305                      Output: ft1.c2
3306                      Remote SQL: SELECT c2 FROM "S 1"."T 1"
3307                ->  Hash
3308                      Output: x.b, x.a
3309                      ->  Subquery Scan on x
3310                            Output: x.b, x.a
3311                            ->  Foreign Scan
3312                                  Output: ft1_1.c2, (sum(ft1_1.c1))
3313                                  Relations: Aggregate on (public.ft1)
3314                                  Remote SQL: SELECT c2, sum("C 1") FROM "S 1"."T 1" GROUP BY 1
3315 (21 rows)
3316
3317 select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2;
3318  count |   b   
3319 -------+-------
3320    100 | 49600
3321    100 | 49700
3322    100 | 49800
3323    100 | 49900
3324    100 | 50000
3325    100 | 50100
3326    100 | 50200
3327    100 | 50300
3328    100 | 50400
3329    100 | 50500
3330 (10 rows)
3331
3332 -- FULL join with IS NULL check in HAVING
3333 explain (verbose, costs off)
3334 select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2;
3335                                                                                                         QUERY PLAN                                                                                                         
3336 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3337  Sort
3338    Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1
3339    Sort Key: (avg(t1.c1)), (sum(t2.c1))
3340    ->  Foreign Scan
3341          Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1
3342          Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
3343          Remote SQL: SELECT avg(r1.c1), sum(r2.c1), r2.c1 FROM ("S 1"."T 3" r1 FULL JOIN "S 1"."T 4" r2 ON (((r1.c1 = r2.c1)))) GROUP BY 3 HAVING ((((avg(r1.c1) IS NULL) AND (sum(r2.c1) < 10)) OR (sum(r2.c1) IS NULL)))
3344 (7 rows)
3345
3346 select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2;
3347          avg         | sum 
3348 ---------------------+-----
3349  51.0000000000000000 |    
3350                      |   3
3351                      |   9
3352 (3 rows)
3353
3354 -- Aggregate over FULL join needing to deparse the joining relations as
3355 -- subqueries.
3356 explain (verbose, costs off)
3357 select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1);
3358                                                                                                                   QUERY PLAN                                                                                                                   
3359 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3360  Foreign Scan
3361    Output: (count(*)), (sum(ft4.c1)), (avg(ft5.c1))
3362    Relations: Aggregate on ((public.ft4) FULL JOIN (public.ft5))
3363    Remote SQL: SELECT count(*), sum(s4.c1), avg(s5.c1) FROM ((SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s4(c1) FULL JOIN (SELECT c1 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))) s5(c1) ON (((s4.c1 = s5.c1))))
3364 (4 rows)
3365
3366 select count(*), sum(t1.c1), avg(t2.c1) from (select c1 from ft4 where c1 between 50 and 60) t1 full join (select c1 from ft5 where c1 between 50 and 60) t2 on (t1.c1 = t2.c1);
3367  count | sum |         avg         
3368 -------+-----+---------------------
3369      8 | 330 | 55.5000000000000000
3370 (1 row)
3371
3372 -- ORDER BY expression is part of the target list but not pushed down to
3373 -- foreign server.
3374 explain (verbose, costs off)
3375 select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1;
3376                                    QUERY PLAN                                   
3377 --------------------------------------------------------------------------------
3378  Sort
3379    Output: (((sum(c2)) * ((random() <= '1'::double precision))::integer))
3380    Sort Key: (((sum(ft1.c2)) * ((random() <= '1'::double precision))::integer))
3381    ->  Foreign Scan
3382          Output: ((sum(c2)) * ((random() <= '1'::double precision))::integer)
3383          Relations: Aggregate on (public.ft1)
3384          Remote SQL: SELECT sum(c2) FROM "S 1"."T 1"
3385 (7 rows)
3386
3387 select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1;
3388  sum  
3389 ------
3390  4500
3391 (1 row)
3392
3393 -- LATERAL join, with parameterization
3394 set enable_hashagg to false;
3395 explain (verbose, costs off)
3396 select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1;
3397                                               QUERY PLAN                                              
3398 ------------------------------------------------------------------------------------------------------
3399  Sort
3400    Output: t1.c2, qry.sum
3401    Sort Key: t1.c2
3402    ->  Nested Loop
3403          Output: t1.c2, qry.sum
3404          ->  Index Scan using t1_pkey on "S 1"."T 1" t1
3405                Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
3406                Index Cond: (t1."C 1" < 100)
3407                Filter: (t1.c2 < 3)
3408          ->  Subquery Scan on qry
3409                Output: qry.sum, t2.c1
3410                Filter: ((t1.c2 * 2) = qry.sum)
3411                ->  Foreign Scan
3412                      Output: (sum((t2.c1 + t1."C 1"))), t2.c1
3413                      Relations: Aggregate on (public.ft2 t2)
3414                      Remote SQL: SELECT sum(("C 1" + $1::integer)), "C 1" FROM "S 1"."T 1" GROUP BY 2
3415 (16 rows)
3416
3417 select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 3 and t1."C 1" < 100 order by 1;
3418  c2 | sum 
3419 ----+-----
3420   1 |   2
3421   2 |   4
3422 (2 rows)
3423
3424 reset enable_hashagg;
3425 -- Check with placeHolderVars
3426 explain (verbose, costs off)
3427 select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b);
3428                                                                         QUERY PLAN                                                                        
3429 ----------------------------------------------------------------------------------------------------------------------------------------------------------
3430  Aggregate
3431    Output: sum(q.a), count(q.b)
3432    ->  Nested Loop Left Join
3433          Output: q.a, q.b
3434          Inner Unique: true
3435          Join Filter: ((ft4.c1)::numeric <= q.b)
3436          ->  Foreign Scan on public.ft4
3437                Output: ft4.c1, ft4.c2, ft4.c3
3438                Remote SQL: SELECT c1 FROM "S 1"."T 3"
3439          ->  Materialize
3440                Output: q.a, q.b
3441                ->  Subquery Scan on q
3442                      Output: q.a, q.b
3443                      ->  Foreign Scan
3444                            Output: 13, (avg(ft1.c1)), NULL::bigint
3445                            Relations: Aggregate on ((public.ft2) LEFT JOIN (public.ft1))
3446                            Remote SQL: SELECT 13, avg(r1."C 1"), NULL::bigint FROM ("S 1"."T 1" r2 LEFT JOIN "S 1"."T 1" r1 ON (((r1."C 1" = r2."C 1"))))
3447 (17 rows)
3448
3449 select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b);
3450  sum | count 
3451 -----+-------
3452  650 |    50
3453 (1 row)
3454
3455 -- Not supported cases
3456 -- Grouping sets
3457 explain (verbose, costs off)
3458 select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last;
3459                                   QUERY PLAN                                  
3460 ------------------------------------------------------------------------------
3461  Sort
3462    Output: c2, (sum(c1))
3463    Sort Key: ft1.c2
3464    ->  MixedAggregate
3465          Output: c2, sum(c1)
3466          Hash Key: ft1.c2
3467          Group Key: ()
3468          ->  Foreign Scan on public.ft1
3469                Output: c2, c1
3470                Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3))
3471 (10 rows)
3472
3473 select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last;
3474  c2 |  sum   
3475 ----+--------
3476   0 |  50500
3477   1 |  49600
3478   2 |  49700
3479     | 149800
3480 (4 rows)
3481
3482 explain (verbose, costs off)
3483 select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last;
3484                                   QUERY PLAN                                  
3485 ------------------------------------------------------------------------------
3486  Sort
3487    Output: c2, (sum(c1))
3488    Sort Key: ft1.c2
3489    ->  MixedAggregate
3490          Output: c2, sum(c1)
3491          Hash Key: ft1.c2
3492          Group Key: ()
3493          ->  Foreign Scan on public.ft1
3494                Output: c2, c1
3495                Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3))
3496 (10 rows)
3497
3498 select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last;
3499  c2 |  sum   
3500 ----+--------
3501   0 |  50500
3502   1 |  49600
3503   2 |  49700
3504     | 149800
3505 (4 rows)
3506
3507 explain (verbose, costs off)
3508 select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last;
3509                                     QUERY PLAN                                    
3510 ----------------------------------------------------------------------------------
3511  Sort
3512    Output: c2, c6, (sum(c1))
3513    Sort Key: ft1.c2, ft1.c6
3514    ->  HashAggregate
3515          Output: c2, c6, sum(c1)
3516          Hash Key: ft1.c2
3517          Hash Key: ft1.c6
3518          ->  Foreign Scan on public.ft1
3519                Output: c2, c6, c1
3520                Remote SQL: SELECT "C 1", c2, c6 FROM "S 1"."T 1" WHERE ((c2 < 3))
3521 (10 rows)
3522
3523 select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last;
3524  c2 | c6 |  sum  
3525 ----+----+-------
3526   0 |    | 50500
3527   1 |    | 49600
3528   2 |    | 49700
3529     | 0  | 50500
3530     | 1  | 49600
3531     | 2  | 49700
3532 (6 rows)
3533
3534 explain (verbose, costs off)
3535 select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last;
3536                                   QUERY PLAN                                  
3537 ------------------------------------------------------------------------------
3538  Sort
3539    Output: c2, (sum(c1)), (GROUPING(c2))
3540    Sort Key: ft1.c2
3541    ->  HashAggregate
3542          Output: c2, sum(c1), GROUPING(c2)
3543          Group Key: ft1.c2
3544          ->  Foreign Scan on public.ft1
3545                Output: c2, c1
3546                Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3))
3547 (9 rows)
3548
3549 select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last;
3550  c2 |  sum  | grouping 
3551 ----+-------+----------
3552   0 | 50500 |        0
3553   1 | 49600 |        0
3554   2 | 49700 |        0
3555 (3 rows)
3556
3557 -- DISTINCT itself is not pushed down, whereas underneath aggregate is pushed
3558 explain (verbose, costs off)
3559 select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1;
3560                                               QUERY PLAN                                               
3561 -------------------------------------------------------------------------------------------------------
3562  Unique
3563    Output: ((sum(c1) / 1000)), c2
3564    ->  Sort
3565          Output: ((sum(c1) / 1000)), c2
3566          Sort Key: ((sum(ft2.c1) / 1000))
3567          ->  Foreign Scan
3568                Output: ((sum(c1) / 1000)), c2
3569                Relations: Aggregate on (public.ft2)
3570                Remote SQL: SELECT (sum("C 1") / 1000), c2 FROM "S 1"."T 1" WHERE ((c2 < 6)) GROUP BY 2
3571 (9 rows)
3572
3573 select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1;
3574  s  
3575 ----
3576  49
3577  50
3578 (2 rows)
3579
3580 -- WindowAgg
3581 explain (verbose, costs off)
3582 select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1;
3583                                                  QUERY PLAN                                                 
3584 ------------------------------------------------------------------------------------------------------------
3585  Sort
3586    Output: c2, (sum(c2)), (count(c2) OVER (?)), ((c2 % 2))
3587    Sort Key: ft2.c2
3588    ->  WindowAgg
3589          Output: c2, (sum(c2)), count(c2) OVER (?), ((c2 % 2))
3590          ->  Sort
3591                Output: c2, ((c2 % 2)), (sum(c2))
3592                Sort Key: ((ft2.c2 % 2))
3593                ->  Foreign Scan
3594                      Output: c2, ((c2 % 2)), (sum(c2))
3595                      Relations: Aggregate on (public.ft2)
3596                      Remote SQL: SELECT c2, (c2 % 2), sum(c2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1
3597 (12 rows)
3598
3599 select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1;
3600  c2 | sum | count 
3601 ----+-----+-------
3602   0 |   0 |     5
3603   1 | 100 |     5
3604   2 | 200 |     5
3605   3 | 300 |     5
3606   4 | 400 |     5
3607   5 | 500 |     5
3608   6 | 600 |     5
3609   7 | 700 |     5
3610   8 | 800 |     5
3611   9 | 900 |     5
3612 (10 rows)
3613
3614 explain (verbose, costs off)
3615 select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1;
3616                                             QUERY PLAN                                             
3617 ---------------------------------------------------------------------------------------------------
3618  Sort
3619    Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2))
3620    Sort Key: ft1.c2
3621    ->  WindowAgg
3622          Output: c2, array_agg(c2) OVER (?), ((c2 % 2))
3623          ->  Sort
3624                Output: c2, ((c2 % 2))
3625                Sort Key: ((ft1.c2 % 2)), ft1.c2 DESC
3626                ->  Foreign Scan
3627                      Output: c2, ((c2 % 2))
3628                      Relations: Aggregate on (public.ft1)
3629                      Remote SQL: SELECT c2, (c2 % 2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1
3630 (12 rows)
3631
3632 select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1;
3633  c2 |  array_agg  
3634 ----+-------------
3635   0 | {8,6,4,2,0}
3636   1 | {9,7,5,3,1}
3637   2 | {8,6,4,2}
3638   3 | {9,7,5,3}
3639   4 | {8,6,4}
3640   5 | {9,7,5}
3641   6 | {8,6}
3642   7 | {9,7}
3643   8 | {8}
3644   9 | {9}
3645 (10 rows)
3646
3647 explain (verbose, costs off)
3648 select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1;
3649                                             QUERY PLAN                                             
3650 ---------------------------------------------------------------------------------------------------
3651  Sort
3652    Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2))
3653    Sort Key: ft1.c2
3654    ->  WindowAgg
3655          Output: c2, array_agg(c2) OVER (?), ((c2 % 2))
3656          ->  Sort
3657                Output: c2, ((c2 % 2))
3658                Sort Key: ((ft1.c2 % 2)), ft1.c2
3659                ->  Foreign Scan
3660                      Output: c2, ((c2 % 2))
3661                      Relations: Aggregate on (public.ft1)
3662                      Remote SQL: SELECT c2, (c2 % 2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY 1
3663 (12 rows)
3664
3665 select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1;
3666  c2 |  array_agg  
3667 ----+-------------
3668   0 | {0,2,4,6,8}
3669   1 | {1,3,5,7,9}
3670   2 | {2,4,6,8}
3671   3 | {3,5,7,9}
3672   4 | {4,6,8}
3673   5 | {5,7,9}
3674   6 | {6,8}
3675   7 | {7,9}
3676   8 | {8}
3677   9 | {9}
3678 (10 rows)
3679
3680 -- ===================================================================
3681 -- parameterized queries
3682 -- ===================================================================
3683 -- simple join
3684 PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $1 AND t2.c1 = $2;
3685 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2);
3686                                                           QUERY PLAN                                                          
3687 ------------------------------------------------------------------------------------------------------------------------------
3688  Foreign Scan
3689    Output: t1.c3, t2.c3
3690    Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
3691    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))))
3692 (4 rows)
3693
3694 EXECUTE st1(1, 1);
3695   c3   |  c3   
3696 -------+-------
3697  00001 | 00001
3698 (1 row)
3699
3700 EXECUTE st1(101, 101);
3701   c3   |  c3   
3702 -------+-------
3703  00101 | 00101
3704 (1 row)
3705
3706 -- subquery using stable function (can't be sent to remote)
3707 PREPARE st2(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c4) = '1970-01-17'::date) ORDER BY c1;
3708 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st2(10, 20);
3709                                                 QUERY PLAN                                                
3710 ----------------------------------------------------------------------------------------------------------
3711  Sort
3712    Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
3713    Sort Key: t1.c1
3714    ->  Nested Loop Semi Join
3715          Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
3716          Join Filter: (t1.c3 = t2.c3)
3717          ->  Foreign Scan on public.ft1 t1
3718                Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
3719                Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 20))
3720          ->  Materialize
3721                Output: t2.c3
3722                ->  Foreign Scan on public.ft2 t2
3723                      Output: t2.c3
3724                      Filter: (date(t2.c4) = '01-17-1970'::date)
3725                      Remote SQL: SELECT c3, c4 FROM "S 1"."T 1" WHERE (("C 1" > 10))
3726 (15 rows)
3727
3728 EXECUTE st2(10, 20);
3729  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
3730 ----+----+-------+------------------------------+--------------------------+----+------------+-----
3731  16 |  6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
3732 (1 row)
3733
3734 EXECUTE st2(101, 121);
3735  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
3736 -----+----+-------+------------------------------+--------------------------+----+------------+-----
3737  116 |  6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
3738 (1 row)
3739
3740 -- subquery using immutable function (can be sent to remote)
3741 PREPARE st3(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 < $2 AND t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 > $1 AND date(c5) = '1970-01-17'::date) ORDER BY c1;
3742 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st3(10, 20);
3743                                                       QUERY PLAN                                                       
3744 -----------------------------------------------------------------------------------------------------------------------
3745  Sort
3746    Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
3747    Sort Key: t1.c1
3748    ->  Nested Loop Semi Join
3749          Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
3750          Join Filter: (t1.c3 = t2.c3)
3751          ->  Foreign Scan on public.ft1 t1
3752                Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
3753                Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 20))
3754          ->  Materialize
3755                Output: t2.c3
3756                ->  Foreign Scan on public.ft2 t2
3757                      Output: t2.c3
3758                      Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" > 10)) AND ((date(c5) = '1970-01-17'::date))
3759 (14 rows)
3760
3761 EXECUTE st3(10, 20);
3762  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
3763 ----+----+-------+------------------------------+--------------------------+----+------------+-----
3764  16 |  6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
3765 (1 row)
3766
3767 EXECUTE st3(20, 30);
3768  c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 
3769 ----+----+----+----+----+----+----+----
3770 (0 rows)
3771
3772 -- custom plan should be chosen initially
3773 PREPARE st4(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 = $1;
3774 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
3775                                          QUERY PLAN                                          
3776 ---------------------------------------------------------------------------------------------
3777  Foreign Scan on public.ft1 t1
3778    Output: c1, c2, c3, c4, c5, c6, c7, c8
3779    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
3780 (3 rows)
3781
3782 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
3783                                          QUERY PLAN                                          
3784 ---------------------------------------------------------------------------------------------
3785  Foreign Scan on public.ft1 t1
3786    Output: c1, c2, c3, c4, c5, c6, c7, c8
3787    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
3788 (3 rows)
3789
3790 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
3791                                          QUERY PLAN                                          
3792 ---------------------------------------------------------------------------------------------
3793  Foreign Scan on public.ft1 t1
3794    Output: c1, c2, c3, c4, c5, c6, c7, c8
3795    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
3796 (3 rows)
3797
3798 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
3799                                          QUERY PLAN                                          
3800 ---------------------------------------------------------------------------------------------
3801  Foreign Scan on public.ft1 t1
3802    Output: c1, c2, c3, c4, c5, c6, c7, c8
3803    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
3804 (3 rows)
3805
3806 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
3807                                          QUERY PLAN                                          
3808 ---------------------------------------------------------------------------------------------
3809  Foreign Scan on public.ft1 t1
3810    Output: c1, c2, c3, c4, c5, c6, c7, c8
3811    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
3812 (3 rows)
3813
3814 -- once we try it enough times, should switch to generic plan
3815 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
3816                                               QUERY PLAN                                               
3817 -------------------------------------------------------------------------------------------------------
3818  Foreign Scan on public.ft1 t1
3819    Output: c1, c2, c3, c4, c5, c6, c7, c8
3820    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
3821 (3 rows)
3822
3823 -- value of $1 should not be sent to remote
3824 PREPARE st5(user_enum,int) AS SELECT * FROM ft1 t1 WHERE c8 = $1 and c1 = $2;
3825 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
3826                                          QUERY PLAN                                          
3827 ---------------------------------------------------------------------------------------------
3828  Foreign Scan on public.ft1 t1
3829    Output: c1, c2, c3, c4, c5, c6, c7, c8
3830    Filter: (t1.c8 = 'foo'::user_enum)
3831    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
3832 (4 rows)
3833
3834 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
3835                                          QUERY PLAN                                          
3836 ---------------------------------------------------------------------------------------------
3837  Foreign Scan on public.ft1 t1
3838    Output: c1, c2, c3, c4, c5, c6, c7, c8
3839    Filter: (t1.c8 = 'foo'::user_enum)
3840    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
3841 (4 rows)
3842
3843 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
3844                                          QUERY PLAN                                          
3845 ---------------------------------------------------------------------------------------------
3846  Foreign Scan on public.ft1 t1
3847    Output: c1, c2, c3, c4, c5, c6, c7, c8
3848    Filter: (t1.c8 = 'foo'::user_enum)
3849    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
3850 (4 rows)
3851
3852 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
3853                                          QUERY PLAN                                          
3854 ---------------------------------------------------------------------------------------------
3855  Foreign Scan on public.ft1 t1
3856    Output: c1, c2, c3, c4, c5, c6, c7, c8
3857    Filter: (t1.c8 = 'foo'::user_enum)
3858    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
3859 (4 rows)
3860
3861 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
3862                                          QUERY PLAN                                          
3863 ---------------------------------------------------------------------------------------------
3864  Foreign Scan on public.ft1 t1
3865    Output: c1, c2, c3, c4, c5, c6, c7, c8
3866    Filter: (t1.c8 = 'foo'::user_enum)
3867    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
3868 (4 rows)
3869
3870 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
3871                                               QUERY PLAN                                               
3872 -------------------------------------------------------------------------------------------------------
3873  Foreign Scan on public.ft1 t1
3874    Output: c1, c2, c3, c4, c5, c6, c7, c8
3875    Filter: (t1.c8 = $1)
3876    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
3877 (4 rows)
3878
3879 EXECUTE st5('foo', 1);
3880  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
3881 ----+----+-------+------------------------------+--------------------------+----+------------+-----
3882   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
3883 (1 row)
3884
3885 -- altering FDW options requires replanning
3886 PREPARE st6 AS SELECT * FROM ft1 t1 WHERE t1.c1 = t1.c2;
3887 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
3888                                           QUERY PLAN                                          
3889 ----------------------------------------------------------------------------------------------
3890  Foreign Scan on public.ft1 t1
3891    Output: c1, c2, c3, c4, c5, c6, c7, c8
3892    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = c2))
3893 (3 rows)
3894
3895 PREPARE st7 AS INSERT INTO ft1 (c1,c2,c3) VALUES (1001,101,'foo');
3896 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
3897                                                                                            QUERY PLAN                                                                                            
3898 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3899  Insert on public.ft1
3900    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)
3901    ->  Result
3902          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
3903 (4 rows)
3904
3905 ALTER TABLE "S 1"."T 1" RENAME TO "T 0";
3906 ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 0');
3907 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st6;
3908                                           QUERY PLAN                                          
3909 ----------------------------------------------------------------------------------------------
3910  Foreign Scan on public.ft1 t1
3911    Output: c1, c2, c3, c4, c5, c6, c7, c8
3912    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 0" WHERE (("C 1" = c2))
3913 (3 rows)
3914
3915 EXECUTE st6;
3916  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
3917 ----+----+-------+------------------------------+--------------------------+----+------------+-----
3918   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
3919   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
3920   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
3921   4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
3922   5 |  5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
3923   6 |  6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
3924   7 |  7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
3925   8 |  8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
3926   9 |  9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
3927 (9 rows)
3928
3929 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st7;
3930                                                                                            QUERY PLAN                                                                                            
3931 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
3932  Insert on public.ft1
3933    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)
3934    ->  Result
3935          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
3936 (4 rows)
3937
3938 ALTER TABLE "S 1"."T 0" RENAME TO "T 1";
3939 ALTER FOREIGN TABLE ft1 OPTIONS (SET table_name 'T 1');
3940 PREPARE st8 AS SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
3941 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
3942                                        QUERY PLAN                                        
3943 -----------------------------------------------------------------------------------------
3944  Foreign Scan
3945    Output: (count(c3))
3946    Relations: Aggregate on (public.ft1 t1)
3947    Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2))
3948 (4 rows)
3949
3950 ALTER SERVER loopback OPTIONS (DROP extensions);
3951 EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st8;
3952                         QUERY PLAN                         
3953 -----------------------------------------------------------
3954  Aggregate
3955    Output: count(c3)
3956    ->  Foreign Scan on public.ft1 t1
3957          Output: c3
3958          Filter: (t1.c1 === t1.c2)
3959          Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
3960 (6 rows)
3961
3962 EXECUTE st8;
3963  count 
3964 -------
3965      9
3966 (1 row)
3967
3968 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
3969 -- cleanup
3970 DEALLOCATE st1;
3971 DEALLOCATE st2;
3972 DEALLOCATE st3;
3973 DEALLOCATE st4;
3974 DEALLOCATE st5;
3975 DEALLOCATE st6;
3976 DEALLOCATE st7;
3977 DEALLOCATE st8;
3978 -- System columns, except ctid and oid, should not be sent to remote
3979 EXPLAIN (VERBOSE, COSTS OFF)
3980 SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
3981                                   QUERY PLAN                                   
3982 -------------------------------------------------------------------------------
3983  Limit
3984    Output: c1, c2, c3, c4, c5, c6, c7, c8
3985    ->  Foreign Scan on public.ft1 t1
3986          Output: c1, c2, c3, c4, c5, c6, c7, c8
3987          Filter: (t1.tableoid = '1259'::oid)
3988          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
3989 (6 rows)
3990
3991 SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1;
3992  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
3993 ----+----+-------+------------------------------+--------------------------+----+------------+-----
3994   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
3995 (1 row)
3996
3997 EXPLAIN (VERBOSE, COSTS OFF)
3998 SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1;
3999                                   QUERY PLAN                                   
4000 -------------------------------------------------------------------------------
4001  Limit
4002    Output: ((tableoid)::regclass), c1, c2, c3, c4, c5, c6, c7, c8
4003    ->  Foreign Scan on public.ft1 t1
4004          Output: (tableoid)::regclass, c1, c2, c3, c4, c5, c6, c7, c8
4005          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
4006 (5 rows)
4007
4008 SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1;
4009  tableoid | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
4010 ----------+----+----+-------+------------------------------+--------------------------+----+------------+-----
4011  ft1      |  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
4012 (1 row)
4013
4014 EXPLAIN (VERBOSE, COSTS OFF)
4015 SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)';
4016                                               QUERY PLAN                                               
4017 -------------------------------------------------------------------------------------------------------
4018  Foreign Scan on public.ft1 t1
4019    Output: c1, c2, c3, c4, c5, c6, c7, c8
4020    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((ctid = '(0,2)'::tid))
4021 (3 rows)
4022
4023 SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)';
4024  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
4025 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4026   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
4027 (1 row)
4028
4029 EXPLAIN (VERBOSE, COSTS OFF)
4030 SELECT ctid, * FROM ft1 t1 LIMIT 1;
4031                                      QUERY PLAN                                      
4032 -------------------------------------------------------------------------------------
4033  Limit
4034    Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8
4035    ->  Foreign Scan on public.ft1 t1
4036          Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8
4037          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1"
4038 (5 rows)
4039
4040 SELECT ctid, * FROM ft1 t1 LIMIT 1;
4041  ctid  | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
4042 -------+----+----+-------+------------------------------+--------------------------+----+------------+-----
4043  (0,1) |  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
4044 (1 row)
4045
4046 EXPLAIN (VERBOSE, COSTS OFF)
4047 SELECT oid, * FROM ft_pg_type WHERE typname = 'int4';
4048                                              QUERY PLAN                                             
4049 ----------------------------------------------------------------------------------------------------
4050  Foreign Scan on public.ft_pg_type
4051    Output: oid, typname, typlen
4052    Remote SQL: SELECT typname, typlen, oid FROM pg_catalog.pg_type WHERE ((typname = 'int4'::name))
4053 (3 rows)
4054
4055 SELECT oid, * FROM ft_pg_type WHERE typname = 'int4';
4056  oid | typname | typlen 
4057 -----+---------+--------
4058   23 | int4    |      4
4059 (1 row)
4060
4061 -- ===================================================================
4062 -- used in PL/pgSQL function
4063 -- ===================================================================
4064 CREATE OR REPLACE FUNCTION f_test(p_c1 int) RETURNS int AS $$
4065 DECLARE
4066         v_c1 int;
4067 BEGIN
4068     SELECT c1 INTO v_c1 FROM ft1 WHERE c1 = p_c1 LIMIT 1;
4069     PERFORM c1 FROM ft1 WHERE c1 = p_c1 AND p_c1 = v_c1 LIMIT 1;
4070     RETURN v_c1;
4071 END;
4072 $$ LANGUAGE plpgsql;
4073 SELECT f_test(100);
4074  f_test 
4075 --------
4076     100
4077 (1 row)
4078
4079 DROP FUNCTION f_test(int);
4080 -- ===================================================================
4081 -- conversion error
4082 -- ===================================================================
4083 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int;
4084 SELECT * FROM ft1 WHERE c1 = 1;  -- ERROR
4085 ERROR:  invalid input syntax for integer: "foo"
4086 CONTEXT:  column "c8" of foreign table "ft1"
4087 SELECT  ft1.c1,  ft2.c2, ft1.c8 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; -- ERROR
4088 ERROR:  invalid input syntax for integer: "foo"
4089 CONTEXT:  column "c8" of foreign table "ft1"
4090 SELECT  ft1.c1,  ft2.c2, ft1 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; -- ERROR
4091 ERROR:  invalid input syntax for integer: "foo"
4092 CONTEXT:  whole-row reference to foreign table "ft1"
4093 SELECT sum(c2), array_agg(c8) FROM ft1 GROUP BY c8; -- ERROR
4094 ERROR:  invalid input syntax for integer: "foo"
4095 CONTEXT:  processing expression at position 2 in select list
4096 ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum;
4097 -- ===================================================================
4098 -- subtransaction
4099 --  + local/remote error doesn't break cursor
4100 -- ===================================================================
4101 BEGIN;
4102 DECLARE c CURSOR FOR SELECT * FROM ft1 ORDER BY c1;
4103 FETCH c;
4104  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
4105 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4106   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
4107 (1 row)
4108
4109 SAVEPOINT s;
4110 ERROR OUT;          -- ERROR
4111 ERROR:  syntax error at or near "ERROR"
4112 LINE 1: ERROR OUT;
4113         ^
4114 ROLLBACK TO s;
4115 FETCH c;
4116  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
4117 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4118   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
4119 (1 row)
4120
4121 SAVEPOINT s;
4122 SELECT * FROM ft1 WHERE 1 / (c1 - 1) > 0;  -- ERROR
4123 ERROR:  division by zero
4124 CONTEXT:  Remote SQL command: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (((1 / ("C 1" - 1)) > 0))
4125 ROLLBACK TO s;
4126 FETCH c;
4127  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
4128 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4129   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
4130 (1 row)
4131
4132 SELECT * FROM ft1 ORDER BY c1 LIMIT 1;
4133  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
4134 ----+----+-------+------------------------------+--------------------------+----+------------+-----
4135   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
4136 (1 row)
4137
4138 COMMIT;
4139 -- ===================================================================
4140 -- test handling of collations
4141 -- ===================================================================
4142 create table loct3 (f1 text collate "C" unique, f2 text, f3 varchar(10) unique);
4143 create foreign table ft3 (f1 text collate "C", f2 text, f3 varchar(10))
4144   server loopback options (table_name 'loct3', use_remote_estimate 'true');
4145 -- can be sent to remote
4146 explain (verbose, costs off) select * from ft3 where f1 = 'foo';
4147                                   QUERY PLAN                                  
4148 ------------------------------------------------------------------------------
4149  Foreign Scan on public.ft3
4150    Output: f1, f2, f3
4151    Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f1 = 'foo'::text))
4152 (3 rows)
4153
4154 explain (verbose, costs off) select * from ft3 where f1 COLLATE "C" = 'foo';
4155                                   QUERY PLAN                                  
4156 ------------------------------------------------------------------------------
4157  Foreign Scan on public.ft3
4158    Output: f1, f2, f3
4159    Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f1 = 'foo'::text))
4160 (3 rows)
4161
4162 explain (verbose, costs off) select * from ft3 where f2 = 'foo';
4163                                   QUERY PLAN                                  
4164 ------------------------------------------------------------------------------
4165  Foreign Scan on public.ft3
4166    Output: f1, f2, f3
4167    Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f2 = 'foo'::text))
4168 (3 rows)
4169
4170 explain (verbose, costs off) select * from ft3 where f3 = 'foo';
4171                                   QUERY PLAN                                  
4172 ------------------------------------------------------------------------------
4173  Foreign Scan on public.ft3
4174    Output: f1, f2, f3
4175    Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f3 = 'foo'::text))
4176 (3 rows)
4177
4178 explain (verbose, costs off) select * from ft3 f, loct3 l
4179   where f.f3 = l.f3 and l.f1 = 'foo';
4180                                             QUERY PLAN                                            
4181 --------------------------------------------------------------------------------------------------
4182  Nested Loop
4183    Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
4184    ->  Index Scan using loct3_f1_key on public.loct3 l
4185          Output: l.f1, l.f2, l.f3
4186          Index Cond: (l.f1 = 'foo'::text)
4187    ->  Foreign Scan on public.ft3 f
4188          Output: f.f1, f.f2, f.f3
4189          Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE (($1::character varying(10) = f3))
4190 (8 rows)
4191
4192 -- can't be sent to remote
4193 explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo';
4194                     QUERY PLAN                     
4195 ---------------------------------------------------
4196  Foreign Scan on public.ft3
4197    Output: f1, f2, f3
4198    Filter: ((ft3.f1)::text = 'foo'::text)
4199    Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4200 (4 rows)
4201
4202 explain (verbose, costs off) select * from ft3 where f1 = 'foo' COLLATE "C";
4203                     QUERY PLAN                     
4204 ---------------------------------------------------
4205  Foreign Scan on public.ft3
4206    Output: f1, f2, f3
4207    Filter: (ft3.f1 = 'foo'::text COLLATE "C")
4208    Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4209 (4 rows)
4210
4211 explain (verbose, costs off) select * from ft3 where f2 COLLATE "C" = 'foo';
4212                     QUERY PLAN                     
4213 ---------------------------------------------------
4214  Foreign Scan on public.ft3
4215    Output: f1, f2, f3
4216    Filter: ((ft3.f2)::text = 'foo'::text)
4217    Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4218 (4 rows)
4219
4220 explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C";
4221                     QUERY PLAN                     
4222 ---------------------------------------------------
4223  Foreign Scan on public.ft3
4224    Output: f1, f2, f3
4225    Filter: (ft3.f2 = 'foo'::text COLLATE "C")
4226    Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4227 (4 rows)
4228
4229 explain (verbose, costs off) select * from ft3 f, loct3 l
4230   where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo';
4231                        QUERY PLAN                        
4232 ---------------------------------------------------------
4233  Nested Loop
4234    Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
4235    Join Filter: ((f.f3)::text = (l.f3)::text)
4236    ->  Index Scan using loct3_f1_key on public.loct3 l
4237          Output: l.f1, l.f2, l.f3
4238          Index Cond: (l.f1 = 'foo'::text)
4239    ->  Foreign Scan on public.ft3 f
4240          Output: f.f1, f.f2, f.f3
4241          Remote SQL: SELECT f1, f2, f3 FROM public.loct3
4242 (9 rows)
4243
4244 -- ===================================================================
4245 -- test writable foreign table stuff
4246 -- ===================================================================
4247 EXPLAIN (verbose, costs off)
4248 INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
4249                                                                                                                     QUERY PLAN                                                                                                                    
4250 --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4251  Insert on public.ft2
4252    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)
4253    ->  Subquery Scan on "*SELECT*"
4254          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
4255          ->  Limit
4256                Output: ((ft2_1.c1 + 1000)), ((ft2_1.c2 + 100)), ((ft2_1.c3 || ft2_1.c3))
4257                ->  Foreign Scan on public.ft2 ft2_1
4258                      Output: (ft2_1.c1 + 1000), (ft2_1.c2 + 100), (ft2_1.c3 || ft2_1.c3)
4259                      Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
4260 (9 rows)
4261
4262 INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
4263 INSERT INTO ft2 (c1,c2,c3)
4264   VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING *;
4265   c1  | c2  | c3  | c4 | c5 | c6 |     c7     | c8 
4266 ------+-----+-----+----+----+----+------------+----
4267  1101 | 201 | aaa |    |    |    | ft2        | 
4268  1102 | 202 | bbb |    |    |    | ft2        | 
4269  1103 | 203 | ccc |    |    |    | ft2        | 
4270 (3 rows)
4271
4272 INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee');
4273 EXPLAIN (verbose, costs off)
4274 UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3;              -- can be pushed down
4275                                                       QUERY PLAN                                                      
4276 ----------------------------------------------------------------------------------------------------------------------
4277  Update on public.ft2
4278    ->  Foreign Update on public.ft2
4279          Remote SQL: UPDATE "S 1"."T 1" SET c2 = (c2 + 300), c3 = (c3 || '_update3'::text) WHERE ((("C 1" % 10) = 3))
4280 (3 rows)
4281
4282 UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3;
4283 EXPLAIN (verbose, costs off)
4284 UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *;  -- can be pushed down
4285                                                                             QUERY PLAN                                                                            
4286 ------------------------------------------------------------------------------------------------------------------------------------------------------------------
4287  Update on public.ft2
4288    Output: c1, c2, c3, c4, c5, c6, c7, c8
4289    ->  Foreign Update on public.ft2
4290          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
4291 (4 rows)
4292
4293 UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *;
4294   c1  | c2  |         c3         |              c4              |            c5            | c6 |     c7     | c8  
4295 ------+-----+--------------------+------------------------------+--------------------------+----+------------+-----
4296     7 | 407 | 00007_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
4297    17 | 407 | 00017_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
4298    27 | 407 | 00027_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
4299    37 | 407 | 00037_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
4300    47 | 407 | 00047_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
4301    57 | 407 | 00057_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
4302    67 | 407 | 00067_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
4303    77 | 407 | 00077_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
4304    87 | 407 | 00087_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
4305    97 | 407 | 00097_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
4306   107 | 407 | 00107_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
4307   117 | 407 | 00117_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
4308   127 | 407 | 00127_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
4309   137 | 407 | 00137_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
4310   147 | 407 | 00147_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
4311   157 | 407 | 00157_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
4312   167 | 407 | 00167_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
4313   177 | 407 | 00177_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
4314   187 | 407 | 00187_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
4315   197 | 407 | 00197_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
4316   207 | 407 | 00207_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
4317   217 | 407 | 00217_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
4318   227 | 407 | 00227_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
4319   237 | 407 | 00237_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
4320   247 | 407 | 00247_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
4321   257 | 407 | 00257_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
4322   267 | 407 | 00267_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
4323   277 | 407 | 00277_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
4324   287 | 407 | 00287_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
4325   297 | 407 | 00297_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
4326   307 | 407 | 00307_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
4327   317 | 407 | 00317_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
4328   327 | 407 | 00327_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
4329   337 | 407 | 00337_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
4330   347 | 407 | 00347_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
4331   357 | 407 | 00357_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
4332   367 | 407 | 00367_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
4333   377 | 407 | 00377_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
4334   387 | 407 | 00387_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
4335   397 | 407 | 00397_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
4336   407 | 407 | 00407_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
4337   417 | 407 | 00417_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
4338   427 | 407 | 00427_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
4339   437 | 407 | 00437_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
4340   447 | 407 | 00447_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
4341   457 | 407 | 00457_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
4342   467 | 407 | 00467_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
4343   477 | 407 | 00477_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
4344   487 | 407 | 00487_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
4345   497 | 407 | 00497_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
4346   507 | 407 | 00507_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
4347   517 | 407 | 00517_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
4348   527 | 407 | 00527_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
4349   537 | 407 | 00537_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
4350   547 | 407 | 00547_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
4351   557 | 407 | 00557_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
4352   567 | 407 | 00567_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
4353   577 | 407 | 00577_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
4354   587 | 407 | 00587_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
4355   597 | 407 | 00597_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
4356   607 | 407 | 00607_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
4357   617 | 407 | 00617_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
4358   627 | 407 | 00627_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
4359   637 | 407 | 00637_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
4360   647 | 407 | 00647_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
4361   657 | 407 | 00657_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
4362   667 | 407 | 00667_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
4363   677 | 407 | 00677_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
4364   687 | 407 | 00687_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
4365   697 | 407 | 00697_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
4366   707 | 407 | 00707_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
4367   717 | 407 | 00717_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
4368   727 | 407 | 00727_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
4369   737 | 407 | 00737_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
4370   747 | 407 | 00747_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
4371   757 | 407 | 00757_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
4372   767 | 407 | 00767_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
4373   777 | 407 | 00777_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
4374   787 | 407 | 00787_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
4375   797 | 407 | 00797_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
4376   807 | 407 | 00807_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
4377   817 | 407 | 00817_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
4378   827 | 407 | 00827_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
4379   837 | 407 | 00837_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
4380   847 | 407 | 00847_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
4381   857 | 407 | 00857_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
4382   867 | 407 | 00867_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
4383   877 | 407 | 00877_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
4384   887 | 407 | 00887_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
4385   897 | 407 | 00897_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
4386   907 | 407 | 00907_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
4387   917 | 407 | 00917_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
4388   927 | 407 | 00927_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
4389   937 | 407 | 00937_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
4390   947 | 407 | 00947_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
4391   957 | 407 | 00957_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
4392   967 | 407 | 00967_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
4393   977 | 407 | 00977_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
4394   987 | 407 | 00987_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
4395   997 | 407 | 00997_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
4396  1007 | 507 | 0000700007_update7 |                              |                          |    | ft2        | 
4397  1017 | 507 | 0001700017_update7 |                              |                          |    | ft2        | 
4398 (102 rows)
4399
4400 EXPLAIN (verbose, costs off)
4401 UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
4402   FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9;                               -- can be pushed down
4403                                                                                                    QUERY PLAN                                                                                                    
4404 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
4405  Update on public.ft2
4406    ->  Foreign Update
4407          Remote SQL: UPDATE "S 1"."T 1" r1 SET c2 = (r1.c2 + 500), c3 = (r1.c3 || '_update9'::text), c7 = 'ft2       '::character(10) FROM "S 1"."T 1" r2 WHERE ((r1.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 9))
4408 (3 rows)
4409
4410 UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
4411   FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9;
4412 EXPLAIN (verbose, costs off)
4413   DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4;                               -- can be pushed down
4414                                          QUERY PLAN                                         
4415 --------------------------------------------------------------------------------------------
4416  Delete on public.ft2
4417    Output: c1, c4
4418    ->  Foreign Delete on public.ft2
4419          Remote SQL: DELETE FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 5)) RETURNING "C 1", c4
4420 (4 rows)
4421
4422 DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4;
4423   c1  |              c4              
4424 ------+------------------------------
4425     5 | Tue Jan 06 00:00:00 1970 PST
4426    15 | Fri Jan 16 00:00:00 1970 PST
4427    25 | Mon Jan 26 00:00:00 1970 PST
4428    35 | Thu Feb 05 00:00:00 1970 PST
4429    45 | Sun Feb 15 00:00:00 1970 PST
4430    55 | Wed Feb 25 00:00:00 1970 PST
4431    65 | Sat Mar 07 00:00:00 1970 PST
4432    75 | Tue Mar 17 00:00:00 1970 PST
4433    85 | Fri Mar 27 00:00:00 1970 PST
4434    95 | Mon Apr 06 00:00:00 1970 PST
4435   105 | Tue Jan 06 00:00:00 1970 PST
4436   115 | Fri Jan 16 00:00:00 1970 PST
4437   125 | Mon Jan 26 00:00:00 1970 PST
4438   135 | Thu Feb 05 00:00:00 1970 PST
4439   145 | Sun Feb 15 00:00:00 1970 PST
4440   155 | Wed Feb 25 00:00:00 1970 PST
4441   165 | Sat Mar 07 00:00:00 1970 PST
4442   175 | Tue Mar 17 00:00:00 1970 PST
4443   185 | Fri Mar 27 00:00:00 1970 PST
4444   195 | Mon Apr 06 00:00:00 1970 PST
4445   205 | Tue Jan 06 00:00:00 1970 PST
4446   215 | Fri Jan 16 00:00:00 1970 PST
4447   225 | Mon Jan 26 00:00:00 1970 PST
4448   235 | Thu Feb 05 00:00:00 1970 PST
4449   245 | Sun Feb 15 00:00:00 1970 PST
4450   255 | Wed Feb 25 00:00:00 1970 PST
4451   265 | Sat Mar 07 00:00:00 1970 PST
4452   275 | Tue Mar 17 00:00:00 1970 PST
4453   285 | Fri Mar 27 00:00:00 1970 PST
4454   295 | Mon Apr 06 00:00:00 1970 PST
4455   305 | Tue Jan 06 00:00:00 1970 PST
4456   315 | Fri Jan 16 00:00:00 1970 PST
4457   325 | Mon Jan 26 00:00:00 1970 PST
4458   335 | Thu Feb 05 00:00:00 1970 PST
4459   345 | Sun Feb 15 00:00:00 1970 PST
4460   355 | Wed Feb 25 00:00:00 1970 PST
4461   365 | Sat Mar 07 00:00:00 1970 PST
4462   375 | Tue Mar 17 00:00:00 1970 PST
4463   385 | Fri Mar 27 00:00:00 1970 PST
4464   395 | Mon Apr 06 00:00:00 1970 PST
4465   405 | Tue Jan 06 00:00:00 1970 PST
4466   415 | Fri Jan 16 00:00:00 1970 PST
4467   425 | Mon Jan 26 00:00:00 1970 PST
4468   435 | Thu Feb 05 00:00:00 1970 PST
4469   445 | Sun Feb 15 00:00:00 1970 PST
4470   455 | Wed Feb 25 00:00:00 1970 PST
4471   465 | Sat Mar 07 00:00:00 1970 PST
4472   475 | Tue Mar 17 00:00:00 1970 PST
4473   485 | Fri Mar 27 00:00:00 1970 PST
4474   495 | Mon Apr 06 00:00:00 1970 PST
4475   505 | Tue Jan 06 00:00:00 1970 PST
4476   515 | Fri Jan 16 00:00:00 1970 PST
4477   525 | Mon Jan 26 00:00:00 1970 PST
4478   535 | Thu Feb 05 00:00:00 1970 PST
4479   545 | Sun Feb 15 00:00:00 1970 PST
4480   555 | Wed Feb 25 00:00:00 1970 PST
4481   565 | Sat Mar 07 00:00:00 1970 PST
4482   575 | Tue Mar 17 00:00:00 1970 PST
4483   585 | Fri Mar 27 00:00:00 1970 PST
4484   595 | Mon Apr 06 00:00:00 1970 PST
4485   605 | Tue Jan 06 00:00:00 1970 PST
4486   615 | Fri Jan 16 00:00:00 1970 PST
4487   625 | Mon Jan 26 00:00:00 1970 PST
4488   635 | Thu Feb 05 00:00:00 1970 PST
4489   645 | Sun Feb 15 00:00:00 1970 PST
4490   655 | Wed Feb 25 00:00:00 1970 PST
4491   665 | Sat Mar 07 00:00:00 1970 PST
4492   675 | Tue Mar 17 00:00:00 1970 PST
4493   685 | Fri Mar 27 00:00:00 1970 PST
4494   695 | Mon Apr 06 00:00:00 1970 PST
4495   705 | Tue Jan 06 00:00:00 1970 PST
4496   715 | Fri Jan 16 00:00:00 1970 PST
4497   725 | Mon Jan 26 00:00:00 1970 PST
4498   735 | Thu Feb 05 00:00:00 1970 PST
4499   745 | Sun Feb 15 00:00:00 1970 PST
4500   755 | Wed Feb 25 00:00:00 1970 PST
4501   765 | Sat Mar 07 00:00:00 1970 PST
4502   775 | Tue Mar 17 00:00:00 1970 PST
4503   785 | Fri Mar 27 00:00:00 1970 PST
4504   795 | Mon Apr 06 00:00:00 1970 PST
4505   805 | Tue Jan 06 00:00:00 1970 PST
4506   815 | Fri Jan 16 00:00:00 1970 PST
4507   825 | Mon Jan 26 00:00:00 1970 PST
4508   835 | Thu Feb 05 00:00:00 1970 PST
4509   845 | Sun Feb 15 00:00:00 1970 PST
4510   855 | Wed Feb 25 00:00:00 1970 PST
4511   865 | Sat Mar 07 00:00:00 1970 PST
4512   875 | Tue Mar 17 00:00:00 1970 PST
4513   885 | Fri Mar 27 00:00:00 1970 PST
4514   895 | Mon Apr 06 00:00:00 1970 PST
4515   905 | Tue Jan 06 00:00:00 1970 PST
4516   915 | Fri Jan 16 00:00:00 1970 PST
4517   925 | Mon Jan 26 00:00:00 1970 PST
4518   935 | Thu Feb 05 00:00:00 1970 PST
4519   945 | Sun Feb 15 00:00:00 1970 PST
4520   955 | Wed Feb 25 00:00:00 1970 PST
4521   965 | Sat Mar 07 00:00:00 1970 PST
4522   975 | Tue Mar 17 00:00:00 1970 PST
4523   985 | Fri Mar 27 00:00:00 1970 PST
4524   995 | Mon Apr 06 00:00:00 1970 PST
4525  1005 | 
4526  1015 | 
4527  1105 | 
4528 (103 rows)
4529
4530 EXPLAIN (verbose, costs off)
4531 DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;                -- can be pushed down
4532                                                          QUERY PLAN                                                         
4533 ----------------------------------------------------------------------------------------------------------------------------
4534  Delete on public.ft2
4535    ->  Foreign Delete
4536          Remote SQL: DELETE FROM "S 1"."T 1" r1 USING "S 1"."T 1" r2 WHERE ((r1.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 2))
4537 (3 rows)
4538
4539 DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;
4540 SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1;
4541   c1  | c2  |         c3         |              c4              
4542 ------+-----+--------------------+------------------------------
4543     1 |   1 | 00001              | Fri Jan 02 00:00:00 1970 PST
4544     3 | 303 | 00003_update3      | Sun Jan 04 00:00:00 1970 PST
4545     4 |   4 | 00004              | Mon Jan 05 00:00:00 1970 PST
4546     6 |   6 | 00006              | Wed Jan 07 00:00:00 1970 PST
4547     7 | 407 | 00007_update7      | Thu Jan 08 00:00:00 1970 PST
4548     8 |   8 | 00008              | Fri Jan 09 00:00:00 1970 PST
4549     9 | 509 | 00009_update9      | Sat Jan 10 00:00:00 1970 PST
4550    10 |   0 | 00010              | Sun Jan 11 00:00:00 1970 PST
4551    11 |   1 | 00011              | Mon Jan 12 00:00:00 1970 PST
4552    13 | 303 | 00013_update3      | Wed Jan 14 00:00:00 1970 PST
4553    14 |   4 | 00014              | Thu Jan 15 00:00:00 1970 PST
4554    16 |   6 | 00016              | Sat Jan 17 00:00:00 1970 PST
4555    17 | 407 | 00017_update7      | Sun Jan 18 00:00:00 1970 PST
4556    18 |   8 | 00018              | Mon Jan 19 00:00:00 1970 PST
4557    19 | 509 | 00019_update9      | Tue Jan 20 00:00:00 1970 PST
4558    20 |   0 | 00020              | Wed Jan 21 00:00:00 1970 PST
4559    21 |   1 | 00021              | Thu Jan 22 00:00:00 1970 PST
4560    23 | 303 | 00023_update3      | Sat Jan 24 00:00:00 1970 PST
4561    24 |   4 | 00024              | Sun Jan 25 00:00:00 1970 PST
4562    26 |   6 | 00026              | Tue Jan 27 00:00:00 1970 PST
4563    27 | 407 | 00027_update7      | Wed Jan 28 00:00:00 1970 PST
4564    28 |   8 | 00028              | Thu Jan 29 00:00:00 1970 PST
4565    29 | 509 | 00029_update9      | Fri Jan 30 00:00:00 1970 PST
4566    30 |   0 | 00030              | Sat Jan 31 00:00:00 1970 PST
4567    31 |   1 | 00031              | Sun Feb 01 00:00:00 1970 PST
4568    33 | 303 | 00033_update3      | Tue Feb 03 00:00:00 1970 PST
4569    34 |   4 | 00034              | Wed Feb 04 00:00:00 1970 PST
4570    36 |   6 | 00036              | Fri Feb 06 00:00:00 1970 PST
4571    37 | 407 | 00037_update7      | Sat Feb 07 00:00:00 1970 PST
4572    38 |   8 | 00038              | Sun Feb 08 00:00:00 1970 PST
4573    39 | 509 | 00039_update9      | Mon Feb 09 00:00:00 1970 PST
4574    40 |   0 | 00040              | Tue Feb 10 00:00:00 1970 PST
4575    41 |   1 | 00041              | Wed Feb 11 00:00:00 1970 PST
4576    43 | 303 | 00043_update3      | Fri Feb 13 00:00:00 1970 PST
4577    44 |   4 | 00044              | Sat Feb 14 00:00:00 1970 PST
4578    46 |   6 | 00046              | Mon Feb 16 00:00:00 1970 PST
4579    47 | 407 | 00047_update7      | Tue Feb 17 00:00:00 1970 PST
4580    48 |   8 | 00048              | Wed Feb 18 00:00:00 1970 PST
4581    49 | 509 | 00049_update9      | Thu Feb 19 00:00:00 1970 PST
4582    50 |   0 | 00050              | Fri Feb 20 00:00:00 1970 PST
4583    51 |   1 | 00051              | Sat Feb 21 00:00:00 1970 PST
4584    53 | 303 | 00053_update3      | Mon Feb 23 00:00:00 1970 PST
4585    54 |   4 | 00054              | Tue Feb 24 00:00:00 1970 PST
4586    56 |   6 | 00056              | Thu Feb 26 00:00:00 1970 PST
4587    57 | 407 | 00057_update7      | Fri Feb 27 00:00:00 1970 PST
4588    58 |   8 | 00058              | Sat Feb 28 00:00:00 1970 PST
4589    59 | 509 | 00059_update9      | Sun Mar 01 00:00:00 1970 PST
4590    60 |   0 | 00060              | Mon Mar 02 00:00:00 1970 PST
4591    61 |   1 | 00061              | Tue Mar 03 00:00:00 1970 PST
4592    63 | 303 | 00063_update3      | Thu Mar 05 00:00:00 1970 PST
4593    64 |   4 | 00064              | Fri Mar 06 00:00:00 1970 PST
4594    66 |   6 | 00066              | Sun Mar 08 00:00:00 1970 PST
4595    67 | 407 | 00067_update7      | Mon Mar 09 00:00:00 1970 PST
4596    68 |   8 | 00068              | Tue Mar 10 00:00:00 1970 PST
4597    69 | 509 | 00069_update9      | Wed Mar 11 00:00:00 1970 PST
4598    70 |   0 | 00070              | Thu Mar 12 00:00:00 1970 PST
4599    71 |   1 | 00071              | Fri Mar 13 00:00:00 1970 PST
4600    73 | 303 | 00073_update3      | Sun Mar 15 00:00:00 1970 PST
4601    74 |   4 | 00074              | Mon Mar 16 00:00:00 1970 PST
4602    76 |   6 | 00076              | Wed Mar 18 00:00:00 1970 PST
4603    77 | 407 | 00077_update7      | Thu Mar 19 00:00:00 1970 PST
4604    78 |   8 | 00078              | Fri Mar 20 00:00:00 1970 PST
4605    79 | 509 | 00079_update9      | Sat Mar 21 00:00:00 1970 PST
4606    80 |   0 | 00080              | Sun Mar 22 00:00:00 1970 PST
4607    81 |   1 | 00081              | Mon Mar 23 00:00:00 1970 PST
4608    83 | 303 | 00083_update3      | Wed Mar 25 00:00:00 1970 PST
4609    84 |   4 | 00084              | Thu Mar 26 00:00:00 1970 PST
4610    86 |   6 | 00086              | Sat Mar 28 00:00:00 1970 PST
4611    87 | 407 | 00087_update7      | Sun Mar 29 00:00:00 1970 PST
4612    88 |   8 | 00088              | Mon Mar 30 00:00:00 1970 PST
4613    89 | 509 | 00089_update9      | Tue Mar 31 00:00:00 1970 PST
4614    90 |   0 | 00090              | Wed Apr 01 00:00:00 1970 PST
4615    91 |   1 | 00091              | Thu Apr 02 00:00:00 1970 PST
4616    93 | 303 | 00093_update3      | Sat Apr 04 00:00:00 1970 PST
4617    94 |   4 | 00094              | Sun Apr 05 00:00:00 1970 PST
4618    96 |   6 | 00096              | Tue Apr 07 00:00:00 1970 PST
4619    97 | 407 | 00097_update7      | Wed Apr 08 00:00:00 1970 PST
4620    98 |   8 | 00098              | Thu Apr 09 00:00:00 1970 PST
4621    99 | 509 | 00099_update9      | Fri Apr 10 00:00:00 1970 PST
4622   100 |   0 | 00100              | Thu Jan 01 00:00:00 1970 PST
4623   101 |   1 | 00101              | Fri Jan 02 00:00:00 1970 PST
4624   103 | 303 | 00103_update3      | Sun Jan 04 00:00:00 1970 PST
4625   104 |   4 | 00104              | Mon Jan 05 00:00:00 1970 PST
4626   106 |   6 | 00106              | Wed Jan 07 00:00:00 1970 PST
4627   107 | 407 | 00107_update7      | Thu Jan 08 00:00:00 1970 PST
4628   108 |   8 | 00108              | Fri Jan 09 00:00:00 1970 PST
4629   109 | 509 | 00109_update9      | Sat Jan 10 00:00:00 1970 PST
4630   110 |   0 | 00110              | Sun Jan 11 00:00:00 1970 PST
4631   111 |   1 | 00111              | Mon Jan 12 00:00:00 1970 PST
4632   113 | 303 | 00113_update3      | Wed Jan 14 00:00:00 1970 PST
4633   114 |   4 | 00114              | Thu Jan 15 00:00:00 1970 PST
4634   116 |   6 | 00116              | Sat Jan 17 00:00:00 1970 PST
4635   117 | 407 | 00117_update7      | Sun Jan 18 00:00:00 1970 PST
4636   118 |   8 | 00118              | Mon Jan 19 00:00:00 1970 PST
4637   119 | 509 | 00119_update9      | Tue Jan 20 00:00:00 1970 PST
4638   120 |   0 | 00120              | Wed Jan 21 00:00:00 1970 PST
4639   121 |   1 | 00121              | Thu Jan 22 00:00:00 1970 PST
4640   123 | 303 | 00123_update3      | Sat Jan 24 00:00:00 1970 PST
4641   124 |   4 | 00124              | Sun Jan 25 00:00:00 1970 PST
4642   126 |   6 | 00126              | Tue Jan 27 00:00:00 1970 PST
4643   127 | 407 | 00127_update7      | Wed Jan 28 00:00:00 1970 PST
4644   128 |   8 | 00128              | Thu Jan 29 00:00:00 1970 PST
4645   129 | 509 | 00129_update9      | Fri Jan 30 00:00:00 1970 PST
4646   130 |   0 | 00130              | Sat Jan 31 00:00:00 1970 PST
4647   131 |   1 | 00131              | Sun Feb 01 00:00:00 1970 PST
4648   133 | 303 | 00133_update3      | Tue Feb 03 00:00:00 1970 PST
4649   134 |   4 | 00134              | Wed Feb 04 00:00:00 1970 PST
4650   136 |   6 | 00136              | Fri Feb 06 00:00:00 1970 PST
4651   137 | 407 | 00137_update7      | Sat Feb 07 00:00:00 1970 PST
4652   138 |   8 | 00138              | Sun Feb 08 00:00:00 1970 PST
4653   139 | 509 | 00139_update9      | Mon Feb 09 00:00:00 1970 PST
4654   140 |   0 | 00140              | Tue Feb 10 00:00:00 1970 PST
4655   141 |   1 | 00141              | Wed Feb 11 00:00:00 1970 PST
4656   143 | 303 | 00143_update3      | Fri Feb 13 00:00:00 1970 PST
4657   144 |   4 | 00144              | Sat Feb 14 00:00:00 1970 PST
4658   146 |   6 | 00146              | Mon Feb 16 00:00:00 1970 PST
4659   147 | 407 | 00147_update7      | Tue Feb 17 00:00:00 1970 PST
4660   148 |   8 | 00148              | Wed Feb 18 00:00:00 1970 PST
4661   149 | 509 | 00149_update9      | Thu Feb 19 00:00:00 1970 PST
4662   150 |   0 | 00150              | Fri Feb 20 00:00:00 1970 PST
4663   151 |   1 | 00151              | Sat Feb 21 00:00:00 1970 PST
4664   153 | 303 | 00153_update3      | Mon Feb 23 00:00:00 1970 PST
4665   154 |   4 | 00154              | Tue Feb 24 00:00:00 1970 PST
4666   156 |   6 | 00156              | Thu Feb 26 00:00:00 1970 PST
4667   157 | 407 | 00157_update7      | Fri Feb 27 00:00:00 1970 PST
4668   158 |   8 | 00158              | Sat Feb 28 00:00:00 1970 PST
4669   159 | 509 | 00159_update9      | Sun Mar 01 00:00:00 1970 PST
4670   160 |   0 | 00160              | Mon Mar 02 00:00:00 1970 PST
4671   161 |   1 | 00161              | Tue Mar 03 00:00:00 1970 PST
4672   163 | 303 | 00163_update3      | Thu Mar 05 00:00:00 1970 PST
4673   164 |   4 | 00164              | Fri Mar 06 00:00:00 1970 PST
4674   166 |   6 | 00166              | Sun Mar 08 00:00:00 1970 PST
4675   167 | 407 | 00167_update7      | Mon Mar 09 00:00:00 1970 PST
4676   168 |   8 | 00168              | Tue Mar 10 00:00:00 1970 PST
4677   169 | 509 | 00169_update9      | Wed Mar 11 00:00:00 1970 PST
4678   170 |   0 | 00170              | Thu Mar 12 00:00:00 1970 PST
4679   171 |   1 | 00171              | Fri Mar 13 00:00:00 1970 PST
4680   173 | 303 | 00173_update3      | Sun Mar 15 00:00:00 1970 PST
4681   174 |   4 | 00174              | Mon Mar 16 00:00:00 1970 PST
4682   176 |   6 | 00176              | Wed Mar 18 00:00:00 1970 PST
4683   177 | 407 | 00177_update7      | Thu Mar 19 00:00:00 1970 PST
4684   178 |   8 | 00178              | Fri Mar 20 00:00:00 1970 PST
4685   179 | 509 | 00179_update9      | Sat Mar 21 00:00:00 1970 PST
4686   180 |   0 | 00180              | Sun Mar 22 00:00:00 1970 PST
4687   181 |   1 | 00181              | Mon Mar 23 00:00:00 1970 PST
4688   183 | 303 | 00183_update3      | Wed Mar 25 00:00:00 1970 PST
4689   184 |   4 | 00184              | Thu Mar 26 00:00:00 1970 PST
4690   186 |   6 | 00186              | Sat Mar 28 00:00:00 1970 PST
4691   187 | 407 | 00187_update7      | Sun Mar 29 00:00:00 1970 PST
4692   188 |   8 | 00188              | Mon Mar 30 00:00:00 1970 PST
4693   189 | 509 | 00189_update9      | Tue Mar 31 00:00:00 1970 PST
4694   190 |   0 | 00190              | Wed Apr 01 00:00:00 1970 PST
4695   191 |   1 | 00191              | Thu Apr 02 00:00:00 1970 PST
4696   193 | 303 | 00193_update3      | Sat Apr 04 00:00:00 1970 PST
4697   194 |   4 | 00194              | Sun Apr 05 00:00:00 1970 PST
4698   196 |   6 | 00196              | Tue Apr 07 00:00:00 1970 PST
4699   197 | 407 | 00197_update7      | Wed Apr 08 00:00:00 1970 PST
4700   198 |   8 | 00198              | Thu Apr 09 00:00:00 1970 PST
4701   199 | 509 | 00199_update9      | Fri Apr 10 00:00:00 1970 PST
4702   200 |   0 | 00200              | Thu Jan 01 00:00:00 1970 PST
4703   201 |   1 | 00201              | Fri Jan 02 00:00:00 1970 PST
4704   203 | 303 | 00203_update3      | Sun Jan 04 00:00:00 1970 PST
4705   204 |   4 | 00204              | Mon Jan 05 00:00:00 1970 PST
4706   206 |   6 | 00206              | Wed Jan 07 00:00:00 1970 PST
4707   207 | 407 | 00207_update7      | Thu Jan 08 00:00:00 1970 PST
4708   208 |   8 | 00208              | Fri Jan 09 00:00:00 1970 PST
4709   209 | 509 | 00209_update9      | Sat Jan 10 00:00:00 1970 PST
4710   210 |   0 | 00210              | Sun Jan 11 00:00:00 1970 PST
4711   211 |   1 | 00211              | Mon Jan 12 00:00:00 1970 PST
4712   213 | 303 | 00213_update3      | Wed Jan 14 00:00:00 1970 PST
4713   214 |   4 | 00214              | Thu Jan 15 00:00:00 1970 PST
4714   216 |   6 | 00216              | Sat Jan 17 00:00:00 1970 PST
4715   217 | 407 | 00217_update7      | Sun Jan 18 00:00:00 1970 PST
4716   218 |   8 | 00218              | Mon Jan 19 00:00:00 1970 PST
4717   219 | 509 | 00219_update9      | Tue Jan 20 00:00:00 1970 PST
4718   220 |   0 | 00220              | Wed Jan 21 00:00:00 1970 PST
4719   221 |   1 | 00221              | Thu Jan 22 00:00:00 1970 PST
4720   223 | 303 | 00223_update3      | Sat Jan 24 00:00:00 1970 PST
4721   224 |   4 | 00224              | Sun Jan 25 00:00:00 1970 PST
4722   226 |   6 | 00226              | Tue Jan 27 00:00:00 1970 PST
4723   227 | 407 | 00227_update7      | Wed Jan 28 00:00:00 1970 PST
4724   228 |   8 | 00228              | Thu Jan 29 00:00:00 1970 PST
4725   229 | 509 | 00229_update9      | Fri Jan 30 00:00:00 1970 PST
4726   230 |   0 | 00230              | Sat Jan 31 00:00:00 1970 PST
4727   231 |   1 | 00231              | Sun Feb 01 00:00:00 1970 PST
4728   233 | 303 | 00233_update3      | Tue Feb 03 00:00:00 1970 PST
4729   234 |   4 | 00234              | Wed Feb 04 00:00:00 1970 PST
4730   236 |   6 | 00236              | Fri Feb 06 00:00:00 1970 PST
4731   237 | 407 | 00237_update7      | Sat Feb 07 00:00:00 1970 PST
4732   238 |   8 | 00238              | Sun Feb 08 00:00:00 1970 PST
4733   239 | 509 | 00239_update9      | Mon Feb 09 00:00:00 1970 PST
4734   240 |   0 | 00240              | Tue Feb 10 00:00:00 1970 PST
4735   241 |   1 | 00241              | Wed Feb 11 00:00:00 1970 PST
4736   243 | 303 | 00243_update3      | Fri Feb 13 00:00:00 1970 PST
4737   244 |   4 | 00244              | Sat Feb 14 00:00:00 1970 PST
4738   246 |   6 | 00246              | Mon Feb 16 00:00:00 1970 PST
4739   247 | 407 | 00247_update7      | Tue Feb 17 00:00:00 1970 PST
4740   248 |   8 | 00248              | Wed Feb 18 00:00:00 1970 PST
4741   249 | 509 | 00249_update9      | Thu Feb 19 00:00:00 1970 PST
4742   250 |   0 | 00250              | Fri Feb 20 00:00:00 1970 PST
4743   251 |   1 | 00251              | Sat Feb 21 00:00:00 1970 PST
4744   253 | 303 | 00253_update3      | Mon Feb 23 00:00:00 1970 PST
4745   254 |   4 | 00254              | Tue Feb 24 00:00:00 1970 PST
4746   256 |   6 | 00256              | Thu Feb 26 00:00:00 1970 PST
4747   257 | 407 | 00257_update7      | Fri Feb 27 00:00:00 1970 PST
4748   258 |   8 | 00258              | Sat Feb 28 00:00:00 1970 PST
4749   259 | 509 | 00259_update9      | Sun Mar 01 00:00:00 1970 PST
4750   260 |   0 | 00260              | Mon Mar 02 00:00:00 1970 PST
4751   261 |   1 | 00261              | Tue Mar 03 00:00:00 1970 PST
4752   263 | 303 | 00263_update3      | Thu Mar 05 00:00:00 1970 PST
4753   264 |   4 | 00264              | Fri Mar 06 00:00:00 1970 PST
4754   266 |   6 | 00266              | Sun Mar 08 00:00:00 1970 PST
4755   267 | 407 | 00267_update7      | Mon Mar 09 00:00:00 1970 PST
4756   268 |   8 | 00268              | Tue Mar 10 00:00:00 1970 PST
4757   269 | 509 | 00269_update9      | Wed Mar 11 00:00:00 1970 PST
4758   270 |   0 | 00270              | Thu Mar 12 00:00:00 1970 PST
4759   271 |   1 | 00271              | Fri Mar 13 00:00:00 1970 PST
4760   273 | 303 | 00273_update3      | Sun Mar 15 00:00:00 1970 PST
4761   274 |   4 | 00274              | Mon Mar 16 00:00:00 1970 PST
4762   276 |   6 | 00276              | Wed Mar 18 00:00:00 1970 PST
4763   277 | 407 | 00277_update7      | Thu Mar 19 00:00:00 1970 PST
4764   278 |   8 | 00278              | Fri Mar 20 00:00:00 1970 PST
4765   279 | 509 | 00279_update9      | Sat Mar 21 00:00:00 1970 PST
4766   280 |   0 | 00280              | Sun Mar 22 00:00:00 1970 PST
4767   281 |   1 | 00281              | Mon Mar 23 00:00:00 1970 PST
4768   283 | 303 | 00283_update3      | Wed Mar 25 00:00:00 1970 PST
4769   284 |   4 | 00284              | Thu Mar 26 00:00:00 1970 PST
4770   286 |   6 | 00286              | Sat Mar 28 00:00:00 1970 PST
4771   287 | 407 | 00287_update7      | Sun Mar 29 00:00:00 1970 PST
4772   288 |   8 | 00288              | Mon Mar 30 00:00:00 1970 PST
4773   289 | 509 | 00289_update9      | Tue Mar 31 00:00:00 1970 PST
4774   290 |   0 | 00290              | Wed Apr 01 00:00:00 1970 PST
4775   291 |   1 | 00291              | Thu Apr 02 00:00:00 1970 PST
4776   293 | 303 | 00293_update3      | Sat Apr 04 00:00:00 1970 PST
4777   294 |   4 | 00294              | Sun Apr 05 00:00:00 1970 PST
4778   296 |   6 | 00296              | Tue Apr 07 00:00:00 1970 PST
4779   297 | 407 | 00297_update7      | Wed Apr 08 00:00:00 1970 PST
4780   298 |   8 | 00298              | Thu Apr 09 00:00:00 1970 PST
4781   299 | 509 | 00299_update9      | Fri Apr 10 00:00:00 1970 PST
4782   300 |   0 | 00300              | Thu Jan 01 00:00:00 1970 PST
4783   301 |   1 | 00301              | Fri Jan 02 00:00:00 1970 PST
4784   303 | 303 | 00303_update3      | Sun Jan 04 00:00:00 1970 PST
4785   304 |   4 | 00304              | Mon Jan 05 00:00:00 1970 PST
4786   306 |   6 | 00306              | Wed Jan 07 00:00:00 1970 PST
4787   307 | 407 | 00307_update7      | Thu Jan 08 00:00:00 1970 PST
4788   308 |   8 | 00308              | Fri Jan 09 00:00:00 1970 PST
4789   309 | 509 | 00309_update9      | Sat Jan 10 00:00:00 1970 PST
4790   310 |   0 | 00310              | Sun Jan 11 00:00:00 1970 PST
4791   311 |   1 | 00311              | Mon Jan 12 00:00:00 1970 PST
4792   313 | 303 | 00313_update3      | Wed Jan 14 00:00:00 1970 PST
4793   314 |   4 | 00314              | Thu Jan 15 00:00:00 1970 PST
4794   316 |   6 | 00316              | Sat Jan 17 00:00:00 1970 PST
4795   317 | 407 | 00317_update7      | Sun Jan 18 00:00:00 1970 PST
4796   318 |   8 | 00318              | Mon Jan 19 00:00:00 1970 PST
4797   319 | 509 | 00319_update9      | Tue Jan 20 00:00:00 1970 PST
4798   320 |   0 | 00320              | Wed Jan 21 00:00:00 1970 PST
4799   321 |   1 | 00321              | Thu Jan 22 00:00:00 1970 PST
4800   323 | 303 | 00323_update3      | Sat Jan 24 00:00:00 1970 PST
4801   324 |   4 | 00324              | Sun Jan 25 00:00:00 1970 PST
4802   326 |   6 | 00326              | Tue Jan 27 00:00:00 1970 PST
4803   327 | 407 | 00327_update7      | Wed Jan 28 00:00:00 1970 PST
4804   328 |   8 | 00328              | Thu Jan 29 00:00:00 1970 PST
4805   329 | 509 | 00329_update9      | Fri Jan 30 00:00:00 1970 PST
4806   330 |   0 | 00330              | Sat Jan 31 00:00:00 1970 PST
4807   331 |   1 | 00331              | Sun Feb 01 00:00:00 1970 PST
4808   333 | 303 | 00333_update3      | Tue Feb 03 00:00:00 1970 PST
4809   334 |   4 | 00334              | Wed Feb 04 00:00:00 1970 PST
4810   336 |   6 | 00336              | Fri Feb 06 00:00:00 1970 PST
4811   337 | 407 | 00337_update7      | Sat Feb 07 00:00:00 1970 PST
4812   338 |   8 | 00338              | Sun Feb 08 00:00:00 1970 PST
4813   339 | 509 | 00339_update9      | Mon Feb 09 00:00:00 1970 PST
4814   340 |   0 | 00340              | Tue Feb 10 00:00:00 1970 PST
4815   341 |   1 | 00341              | Wed Feb 11 00:00:00 1970 PST
4816   343 | 303 | 00343_update3      | Fri Feb 13 00:00:00 1970 PST
4817   344 |   4 | 00344              | Sat Feb 14 00:00:00 1970 PST
4818   346 |   6 | 00346              | Mon Feb 16 00:00:00 1970 PST
4819   347 | 407 | 00347_update7      | Tue Feb 17 00:00:00 1970 PST
4820   348 |   8 | 00348              | Wed Feb 18 00:00:00 1970 PST
4821   349 | 509 | 00349_update9      | Thu Feb 19 00:00:00 1970 PST
4822   350 |   0 | 00350              | Fri Feb 20 00:00:00 1970 PST
4823   351 |   1 | 00351              | Sat Feb 21 00:00:00 1970 PST
4824   353 | 303 | 00353_update3      | Mon Feb 23 00:00:00 1970 PST
4825   354 |   4 | 00354              | Tue Feb 24 00:00:00 1970 PST
4826   356 |   6 | 00356              | Thu Feb 26 00:00:00 1970 PST
4827   357 | 407 | 00357_update7      | Fri Feb 27 00:00:00 1970 PST
4828   358 |   8 | 00358              | Sat Feb 28 00:00:00 1970 PST
4829   359 | 509 | 00359_update9      | Sun Mar 01 00:00:00 1970 PST
4830   360 |   0 | 00360              | Mon Mar 02 00:00:00 1970 PST
4831   361 |   1 | 00361              | Tue Mar 03 00:00:00 1970 PST
4832   363 | 303 | 00363_update3      | Thu Mar 05 00:00:00 1970 PST
4833   364 |   4 | 00364              | Fri Mar 06 00:00:00 1970 PST
4834   366 |   6 | 00366              | Sun Mar 08 00:00:00 1970 PST
4835   367 | 407 | 00367_update7      | Mon Mar 09 00:00:00 1970 PST
4836   368 |   8 | 00368              | Tue Mar 10 00:00:00 1970 PST
4837   369 | 509 | 00369_update9      | Wed Mar 11 00:00:00 1970 PST
4838   370 |   0 | 00370              | Thu Mar 12 00:00:00 1970 PST
4839   371 |   1 | 00371              | Fri Mar 13 00:00:00 1970 PST
4840   373 | 303 | 00373_update3      | Sun Mar 15 00:00:00 1970 PST
4841   374 |   4 | 00374              | Mon Mar 16 00:00:00 1970 PST
4842   376 |   6 | 00376              | Wed Mar 18 00:00:00 1970 PST
4843   377 | 407 | 00377_update7      | Thu Mar 19 00:00:00 1970 PST
4844   378 |   8 | 00378              | Fri Mar 20 00:00:00 1970 PST
4845   379 | 509 | 00379_update9      | Sat Mar 21 00:00:00 1970 PST
4846   380 |   0 | 00380              | Sun Mar 22 00:00:00 1970 PST
4847   381 |   1 | 00381              | Mon Mar 23 00:00:00 1970 PST
4848   383 | 303 | 00383_update3      | Wed Mar 25 00:00:00 1970 PST
4849   384 |   4 | 00384              | Thu Mar 26 00:00:00 1970 PST
4850   386 |   6 | 00386              | Sat Mar 28 00:00:00 1970 PST
4851   387 | 407 | 00387_update7      | Sun Mar 29 00:00:00 1970 PST
4852   388 |   8 | 00388              | Mon Mar 30 00:00:00 1970 PST
4853   389 | 509 | 00389_update9      | Tue Mar 31 00:00:00 1970 PST
4854   390 |   0 | 00390              | Wed Apr 01 00:00:00 1970 PST
4855   391 |   1 | 00391              | Thu Apr 02 00:00:00 1970 PST
4856   393 | 303 | 00393_update3      | Sat Apr 04 00:00:00 1970 PST
4857   394 |   4 | 00394              | Sun Apr 05 00:00:00 1970 PST
4858   396 |   6 | 00396              | Tue Apr 07 00:00:00 1970 PST
4859   397 | 407 | 00397_update7      | Wed Apr 08 00:00:00 1970 PST
4860   398 |   8 | 00398              | Thu Apr 09 00:00:00 1970 PST
4861   399 | 509 | 00399_update9      | Fri Apr 10 00:00:00 1970 PST
4862   400 |   0 | 00400              | Thu Jan 01 00:00:00 1970 PST
4863   401 |   1 | 00401              | Fri Jan 02 00:00:00 1970 PST
4864   403 | 303 | 00403_update3      | Sun Jan 04 00:00:00 1970 PST
4865   404 |   4 | 00404              | Mon Jan 05 00:00:00 1970 PST
4866   406 |   6 | 00406              | Wed Jan 07 00:00:00 1970 PST
4867   407 | 407 | 00407_update7      | Thu Jan 08 00:00:00 1970 PST
4868   408 |   8 | 00408              | Fri Jan 09 00:00:00 1970 PST
4869   409 | 509 | 00409_update9      | Sat Jan 10 00:00:00 1970 PST
4870   410 |   0 | 00410              | Sun Jan 11 00:00:00 1970 PST
4871   411 |   1 | 00411              | Mon Jan 12 00:00:00 1970 PST
4872   413 | 303 | 00413_update3      | Wed Jan 14 00:00:00 1970 PST
4873   414 |   4 | 00414              | Thu Jan 15 00:00:00 1970 PST
4874   416 |   6 | 00416              | Sat Jan 17 00:00:00 1970 PST
4875   417 | 407 | 00417_update7      | Sun Jan 18 00:00:00 1970 PST
4876   418 |   8 | 00418              | Mon Jan 19 00:00:00 1970 PST
4877   419 | 509 | 00419_update9      | Tue Jan 20 00:00:00 1970 PST
4878   420 |   0 | 00420              | Wed Jan 21 00:00:00 1970 PST
4879   421 |   1 | 00421              | Thu Jan 22 00:00:00 1970 PST
4880   423 | 303 | 00423_update3      | Sat Jan 24 00:00:00 1970 PST
4881   424 |   4 | 00424              | Sun Jan 25 00:00:00 1970 PST
4882   426 |   6 | 00426              | Tue Jan 27 00:00:00 1970 PST
4883   427 | 407 | 00427_update7      | Wed Jan 28 00:00:00 1970 PST
4884   428 |   8 | 00428              | Thu Jan 29 00:00:00 1970 PST
4885   429 | 509 | 00429_update9      | Fri Jan 30 00:00:00 1970 PST
4886   430 |   0 | 00430              | Sat Jan 31 00:00:00 1970 PST
4887   431 |   1 | 00431              | Sun Feb 01 00:00:00 1970 PST
4888   433 | 303 | 00433_update3      | Tue Feb 03 00:00:00 1970 PST
4889   434 |   4 | 00434              | Wed Feb 04 00:00:00 1970 PST
4890   436 |   6 | 00436              | Fri Feb 06 00:00:00 1970 PST
4891   437 | 407 | 00437_update7      | Sat Feb 07 00:00:00 1970 PST
4892   438 |   8 | 00438              | Sun Feb 08 00:00:00 1970 PST
4893   439 | 509 | 00439_update9      | Mon Feb 09 00:00:00 1970 PST
4894   440 |   0 | 00440              | Tue Feb 10 00:00:00 1970 PST
4895   441 |   1 | 00441              | Wed Feb 11 00:00:00 1970 PST
4896   443 | 303 | 00443_update3      | Fri Feb 13 00:00:00 1970 PST
4897   444 |   4 | 00444              | Sat Feb 14 00:00:00 1970 PST
4898   446 |   6 | 00446              | Mon Feb 16 00:00:00 1970 PST
4899   447 | 407 | 00447_update7      | Tue Feb 17 00:00:00 1970 PST
4900   448 |   8 | 00448              | Wed Feb 18 00:00:00 1970 PST
4901   449 | 509 | 00449_update9      | Thu Feb 19 00:00:00 1970 PST
4902   450 |   0 | 00450              | Fri Feb 20 00:00:00 1970 PST
4903   451 |   1 | 00451              | Sat Feb 21 00:00:00 1970 PST
4904   453 | 303 | 00453_update3      | Mon Feb 23 00:00:00 1970 PST
4905   454 |   4 | 00454              | Tue Feb 24 00:00:00 1970 PST
4906   456 |   6 | 00456              | Thu Feb 26 00:00:00 1970 PST
4907   457 | 407 | 00457_update7      | Fri Feb 27 00:00:00 1970 PST
4908   458 |   8 | 00458              | Sat Feb 28 00:00:00 1970 PST
4909   459 | 509 | 00459_update9      | Sun Mar 01 00:00:00 1970 PST
4910   460 |   0 | 00460              | Mon Mar 02 00:00:00 1970 PST
4911   461 |   1 | 00461              | Tue Mar 03 00:00:00 1970 PST
4912   463 | 303 | 00463_update3      | Thu Mar 05 00:00:00 1970 PST
4913   464 |   4 | 00464              | Fri Mar 06 00:00:00 1970 PST
4914   466 |   6 | 00466              | Sun Mar 08 00:00:00 1970 PST
4915   467 | 407 | 00467_update7      | Mon Mar 09 00:00:00 1970 PST
4916   468 |   8 | 00468              | Tue Mar 10 00:00:00 1970 PST
4917   469 | 509 | 00469_update9      | Wed Mar 11 00:00:00 1970 PST
4918   470 |   0 | 00470              | Thu Mar 12 00:00:00 1970 PST
4919   471 |   1 | 00471              | Fri Mar 13 00:00:00 1970 PST
4920   473 | 303 | 00473_update3      | Sun Mar 15 00:00:00 1970 PST
4921   474 |   4 | 00474              | Mon Mar 16 00:00:00 1970 PST
4922   476 |   6 | 00476              | Wed Mar 18 00:00:00 1970 PST
4923   477 | 407 | 00477_update7      | Thu Mar 19 00:00:00 1970 PST
4924   478 |   8 | 00478              | Fri Mar 20 00:00:00 1970 PST
4925   479 | 509 | 00479_update9      | Sat Mar 21 00:00:00 1970 PST
4926   480 |   0 | 00480              | Sun Mar 22 00:00:00 1970 PST
4927   481 |   1 | 00481              | Mon Mar 23 00:00:00 1970 PST
4928   483 | 303 | 00483_update3      | Wed Mar 25 00:00:00 1970 PST
4929   484 |   4 | 00484              | Thu Mar 26 00:00:00 1970 PST
4930   486 |   6 | 00486              | Sat Mar 28 00:00:00 1970 PST
4931   487 | 407 | 00487_update7      | Sun Mar 29 00:00:00 1970 PST
4932   488 |   8 | 00488              | Mon Mar 30 00:00:00 1970 PST
4933   489 | 509 | 00489_update9      | Tue Mar 31 00:00:00 1970 PST
4934   490 |   0 | 00490              | Wed Apr 01 00:00:00 1970 PST
4935   491 |   1 | 00491              | Thu Apr 02 00:00:00 1970 PST
4936   493 | 303 | 00493_update3      | Sat Apr 04 00:00:00 1970 PST
4937   494 |   4 | 00494              | Sun Apr 05 00:00:00 1970 PST
4938   496 |   6 | 00496              | Tue Apr 07 00:00:00 1970 PST
4939   497 | 407 | 00497_update7      | Wed Apr 08 00:00:00 1970 PST
4940   498 |   8 | 00498              | Thu Apr 09 00:00:00 1970 PST
4941   499 | 509 | 00499_update9      | Fri Apr 10 00:00:00 1970 PST
4942   500 |   0 | 00500              | Thu Jan 01 00:00:00 1970 PST
4943   501 |   1 | 00501              | Fri Jan 02 00:00:00 1970 PST
4944   503 | 303 | 00503_update3      | Sun Jan 04 00:00:00 1970 PST
4945   504 |   4 | 00504              | Mon Jan 05 00:00:00 1970 PST
4946   506 |   6 | 00506              | Wed Jan 07 00:00:00 1970 PST
4947   507 | 407 | 00507_update7      | Thu Jan 08 00:00:00 1970 PST
4948   508 |   8 | 00508              | Fri Jan 09 00:00:00 1970 PST
4949   509 | 509 | 00509_update9      | Sat Jan 10 00:00:00 1970 PST
4950   510 |   0 | 00510              | Sun Jan 11 00:00:00 1970 PST
4951   511 |   1 | 00511              | Mon Jan 12 00:00:00 1970 PST
4952   513 | 303 | 00513_update3      | Wed Jan 14 00:00:00 1970 PST
4953   514 |   4 | 00514              | Thu Jan 15 00:00:00 1970 PST
4954   516 |   6 | 00516              | Sat Jan 17 00:00:00 1970 PST
4955   517 | 407 | 00517_update7      | Sun Jan 18 00:00:00 1970 PST
4956   518 |   8 | 00518              | Mon Jan 19 00:00:00 1970 PST
4957   519 | 509 | 00519_update9      | Tue Jan 20 00:00:00 1970 PST
4958   520 |   0 | 00520              | Wed Jan 21 00:00:00 1970 PST
4959   521 |   1 | 00521              | Thu Jan 22 00:00:00 1970 PST
4960   523 | 303 | 00523_update3      | Sat Jan 24 00:00:00 1970 PST
4961   524 |   4 | 00524              | Sun Jan 25 00:00:00 1970 PST
4962   526 |   6 | 00526              | Tue Jan 27 00:00:00 1970 PST
4963   527 | 407 | 00527_update7      | Wed Jan 28 00:00:00 1970 PST
4964   528 |   8 | 00528              | Thu Jan 29 00:00:00 1970 PST
4965   529 | 509 | 00529_update9      | Fri Jan 30 00:00:00 1970 PST
4966   530 |   0 | 00530              | Sat Jan 31 00:00:00 1970 PST
4967   531 |   1 | 00531              | Sun Feb 01 00:00:00 1970 PST
4968   533 | 303 | 00533_update3      | Tue Feb 03 00:00:00 1970 PST
4969   534 |   4 | 00534              | Wed Feb 04 00:00:00 1970 PST
4970   536 |   6 | 00536              | Fri Feb 06 00:00:00 1970 PST
4971   537 | 407 | 00537_update7      | Sat Feb 07 00:00:00 1970 PST
4972   538 |   8 | 00538              | Sun Feb 08 00:00:00 1970 PST
4973   539 | 509 | 00539_update9      | Mon Feb 09 00:00:00 1970 PST
4974   540 |   0 | 00540              | Tue Feb 10 00:00:00 1970 PST
4975   541 |   1 | 00541              | Wed Feb 11 00:00:00 1970 PST
4976   543 | 303 | 00543_update3      | Fri Feb 13 00:00:00 1970 PST
4977   544 |   4 | 00544              | Sat Feb 14 00:00:00 1970 PST
4978   546 |   6 | 00546              | Mon Feb 16 00:00:00 1970 PST
4979   547 | 407 | 00547_update7      | Tue Feb 17 00:00:00 1970 PST
4980   548 |   8 | 00548              | Wed Feb 18 00:00:00 1970 PST
4981   549 | 509 | 00549_update9      | Thu Feb 19 00:00:00 1970 PST
4982   550 |   0 | 00550              | Fri Feb 20 00:00:00 1970 PST
4983   551 |   1 | 00551              | Sat Feb 21 00:00:00 1970 PST
4984   553 | 303 | 00553_update3      | Mon Feb 23 00:00:00 1970 PST
4985   554 |   4 | 00554              | Tue Feb 24 00:00:00 1970 PST
4986   556 |   6 | 00556              | Thu Feb 26 00:00:00 1970 PST
4987   557 | 407 | 00557_update7      | Fri Feb 27 00:00:00 1970 PST
4988   558 |   8 | 00558              | Sat Feb 28 00:00:00 1970 PST
4989   559 | 509 | 00559_update9      | Sun Mar 01 00:00:00 1970 PST
4990   560 |   0 | 00560              | Mon Mar 02 00:00:00 1970 PST
4991   561 |   1 | 00561              | Tue Mar 03 00:00:00 1970 PST
4992   563 | 303 | 00563_update3      | Thu Mar 05 00:00:00 1970 PST
4993   564 |   4 | 00564              | Fri Mar 06 00:00:00 1970 PST
4994   566 |   6 | 00566              | Sun Mar 08 00:00:00 1970 PST
4995   567 | 407 | 00567_update7      | Mon Mar 09 00:00:00 1970 PST
4996   568 |   8 | 00568              | Tue Mar 10 00:00:00 1970 PST
4997   569 | 509 | 00569_update9      | Wed Mar 11 00:00:00 1970 PST
4998   570 |   0 | 00570              | Thu Mar 12 00:00:00 1970 PST
4999   571 |   1 | 00571              | Fri Mar 13 00:00:00 1970 PST
5000   573 | 303 | 00573_update3      | Sun Mar 15 00:00:00 1970 PST
5001   574 |   4 | 00574              | Mon Mar 16 00:00:00 1970 PST
5002   576 |   6 | 00576              | Wed Mar 18 00:00:00 1970 PST
5003   577 | 407 | 00577_update7      | Thu Mar 19 00:00:00 1970 PST
5004   578 |   8 | 00578              | Fri Mar 20 00:00:00 1970 PST
5005   579 | 509 | 00579_update9      | Sat Mar 21 00:00:00 1970 PST
5006   580 |   0 | 00580              | Sun Mar 22 00:00:00 1970 PST
5007   581 |   1 | 00581              | Mon Mar 23 00:00:00 1970 PST
5008   583 | 303 | 00583_update3      | Wed Mar 25 00:00:00 1970 PST
5009   584 |   4 | 00584              | Thu Mar 26 00:00:00 1970 PST
5010   586 |   6 | 00586              | Sat Mar 28 00:00:00 1970 PST
5011   587 | 407 | 00587_update7      | Sun Mar 29 00:00:00 1970 PST
5012   588 |   8 | 00588              | Mon Mar 30 00:00:00 1970 PST
5013   589 | 509 | 00589_update9      | Tue Mar 31 00:00:00 1970 PST
5014   590 |   0 | 00590              | Wed Apr 01 00:00:00 1970 PST
5015   591 |   1 | 00591              | Thu Apr 02 00:00:00 1970 PST
5016   593 | 303 | 00593_update3      | Sat Apr 04 00:00:00 1970 PST
5017   594 |   4 | 00594              | Sun Apr 05 00:00:00 1970 PST
5018   596 |   6 | 00596              | Tue Apr 07 00:00:00 1970 PST
5019   597 | 407 | 00597_update7      | Wed Apr 08 00:00:00 1970 PST
5020   598 |   8 | 00598              | Thu Apr 09 00:00:00 1970 PST
5021   599 | 509 | 00599_update9      | Fri Apr 10 00:00:00 1970 PST
5022   600 |   0 | 00600              | Thu Jan 01 00:00:00 1970 PST
5023   601 |   1 | 00601              | Fri Jan 02 00:00:00 1970 PST
5024   603 | 303 | 00603_update3      | Sun Jan 04 00:00:00 1970 PST
5025   604 |   4 | 00604              | Mon Jan 05 00:00:00 1970 PST
5026   606 |   6 | 00606              | Wed Jan 07 00:00:00 1970 PST
5027   607 | 407 | 00607_update7      | Thu Jan 08 00:00:00 1970 PST
5028   608 |   8 | 00608              | Fri Jan 09 00:00:00 1970 PST
5029   609 | 509 | 00609_update9      | Sat Jan 10 00:00:00 1970 PST
5030   610 |   0 | 00610              | Sun Jan 11 00:00:00 1970 PST
5031   611 |   1 | 00611              | Mon Jan 12 00:00:00 1970 PST
5032   613 | 303 | 00613_update3      | Wed Jan 14 00:00:00 1970 PST
5033   614 |   4 | 00614              | Thu Jan 15 00:00:00 1970 PST
5034   616 |   6 | 00616              | Sat Jan 17 00:00:00 1970 PST
5035   617 | 407 | 00617_update7      | Sun Jan 18 00:00:00 1970 PST
5036   618 |   8 | 00618              | Mon Jan 19 00:00:00 1970 PST
5037   619 | 509 | 00619_update9      | Tue Jan 20 00:00:00 1970 PST
5038   620 |   0 | 00620              | Wed Jan 21 00:00:00 1970 PST
5039   621 |   1 | 00621              | Thu Jan 22 00:00:00 1970 PST
5040   623 | 303 | 00623_update3      | Sat Jan 24 00:00:00 1970 PST
5041   624 |   4 | 00624              | Sun Jan 25 00:00:00 1970 PST
5042   626 |   6 | 00626              | Tue Jan 27 00:00:00 1970 PST
5043   627 | 407 | 00627_update7      | Wed Jan 28 00:00:00 1970 PST
5044   628 |   8 | 00628              | Thu Jan 29 00:00:00 1970 PST
5045   629 | 509 | 00629_update9      | Fri Jan 30 00:00:00 1970 PST
5046   630 |   0 | 00630              | Sat Jan 31 00:00:00 1970 PST
5047   631 |   1 | 00631              | Sun Feb 01 00:00:00 1970 PST
5048   633 | 303 | 00633_update3      | Tue Feb 03 00:00:00 1970 PST
5049   634 |   4 | 00634              | Wed Feb 04 00:00:00 1970 PST
5050   636 |   6 | 00636              | Fri Feb 06 00:00:00 1970 PST
5051   637 | 407 | 00637_update7      | Sat Feb 07 00:00:00 1970 PST
5052   638 |   8 | 00638              | Sun Feb 08 00:00:00 1970 PST
5053   639 | 509 | 00639_update9      | Mon Feb 09 00:00:00 1970 PST
5054   640 |   0 | 00640              | Tue Feb 10 00:00:00 1970 PST
5055   641 |   1 | 00641              | Wed Feb 11 00:00:00 1970 PST
5056   643 | 303 | 00643_update3      | Fri Feb 13 00:00:00 1970 PST
5057   644 |   4 | 00644              | Sat Feb 14 00:00:00 1970 PST
5058   646 |   6 | 00646              | Mon Feb 16 00:00:00 1970 PST
5059   647 | 407 | 00647_update7      | Tue Feb 17 00:00:00 1970 PST
5060   648 |   8 | 00648              | Wed Feb 18 00:00:00 1970 PST
5061   649 | 509 | 00649_update9      | Thu Feb 19 00:00:00 1970 PST
5062   650 |   0 | 00650              | Fri Feb 20 00:00:00 1970 PST
5063   651 |   1 | 00651              | Sat Feb 21 00:00:00 1970 PST
5064   653 | 303 | 00653_update3      | Mon Feb 23 00:00:00 1970 PST
5065   654 |   4 | 00654              | Tue Feb 24 00:00:00 1970 PST
5066   656 |   6 | 00656              | Thu Feb 26 00:00:00 1970 PST
5067   657 | 407 | 00657_update7      | Fri Feb 27 00:00:00 1970 PST
5068   658 |   8 | 00658              | Sat Feb 28 00:00:00 1970 PST
5069   659 | 509 | 00659_update9      | Sun Mar 01 00:00:00 1970 PST
5070   660 |   0 | 00660              | Mon Mar 02 00:00:00 1970 PST
5071   661 |   1 | 00661              | Tue Mar 03 00:00:00 1970 PST
5072   663 | 303 | 00663_update3      | Thu Mar 05 00:00:00 1970 PST
5073   664 |   4 | 00664              | Fri Mar 06 00:00:00 1970 PST
5074   666 |   6 | 00666              | Sun Mar 08 00:00:00 1970 PST
5075   667 | 407 | 00667_update7      | Mon Mar 09 00:00:00 1970 PST
5076   668 |   8 | 00668              | Tue Mar 10 00:00:00 1970 PST
5077   669 | 509 | 00669_update9      | Wed Mar 11 00:00:00 1970 PST
5078   670 |   0 | 00670              | Thu Mar 12 00:00:00 1970 PST
5079   671 |   1 | 00671              | Fri Mar 13 00:00:00 1970 PST
5080   673 | 303 | 00673_update3      | Sun Mar 15 00:00:00 1970 PST
5081   674 |   4 | 00674              | Mon Mar 16 00:00:00 1970 PST
5082   676 |   6 | 00676              | Wed Mar 18 00:00:00 1970 PST
5083   677 | 407 | 00677_update7      | Thu Mar 19 00:00:00 1970 PST
5084   678 |   8 | 00678              | Fri Mar 20 00:00:00 1970 PST
5085   679 | 509 | 00679_update9      | Sat Mar 21 00:00:00 1970 PST
5086   680 |   0 | 00680              | Sun Mar 22 00:00:00 1970 PST
5087   681 |   1 | 00681              | Mon Mar 23 00:00:00 1970 PST
5088   683 | 303 | 00683_update3      | Wed Mar 25 00:00:00 1970 PST
5089   684 |   4 | 00684              | Thu Mar 26 00:00:00 1970 PST
5090   686 |   6 | 00686              | Sat Mar 28 00:00:00 1970 PST
5091   687 | 407 | 00687_update7      | Sun Mar 29 00:00:00 1970 PST
5092   688 |   8 | 00688              | Mon Mar 30 00:00:00 1970 PST
5093   689 | 509 | 00689_update9      | Tue Mar 31 00:00:00 1970 PST
5094   690 |   0 | 00690              | Wed Apr 01 00:00:00 1970 PST
5095   691 |   1 | 00691              | Thu Apr 02 00:00:00 1970 PST
5096   693 | 303 | 00693_update3      | Sat Apr 04 00:00:00 1970 PST
5097   694 |   4 | 00694              | Sun Apr 05 00:00:00 1970 PST
5098   696 |   6 | 00696              | Tue Apr 07 00:00:00 1970 PST
5099   697 | 407 | 00697_update7      | Wed Apr 08 00:00:00 1970 PST
5100   698 |   8 | 00698              | Thu Apr 09 00:00:00 1970 PST
5101   699 | 509 | 00699_update9      | Fri Apr 10 00:00:00 1970 PST
5102   700 |   0 | 00700              | Thu Jan 01 00:00:00 1970 PST
5103   701 |   1 | 00701              | Fri Jan 02 00:00:00 1970 PST
5104   703 | 303 | 00703_update3      | Sun Jan 04 00:00:00 1970 PST
5105   704 |   4 | 00704              | Mon Jan 05 00:00:00 1970 PST
5106   706 |   6 | 00706              | Wed Jan 07 00:00:00 1970 PST
5107   707 | 407 | 00707_update7      | Thu Jan 08 00:00:00 1970 PST
5108   708 |   8 | 00708              | Fri Jan 09 00:00:00 1970 PST
5109   709 | 509 | 00709_update9      | Sat Jan 10 00:00:00 1970 PST
5110   710 |   0 | 00710              | Sun Jan 11 00:00:00 1970 PST
5111   711 |   1 | 00711              | Mon Jan 12 00:00:00 1970 PST
5112   713 | 303 | 00713_update3      | Wed Jan 14 00:00:00 1970 PST
5113   714 |   4 | 00714              | Thu Jan 15 00:00:00 1970 PST
5114   716 |   6 | 00716              | Sat Jan 17 00:00:00 1970 PST
5115   717 | 407 | 00717_update7      | Sun Jan 18 00:00:00 1970 PST
5116   718 |   8 | 00718              | Mon Jan 19 00:00:00 1970 PST
5117   719 | 509 | 00719_update9      | Tue Jan 20 00:00:00 1970 PST
5118   720 |   0 | 00720              | Wed Jan 21 00:00:00 1970 PST
5119   721 |   1 | 00721              | Thu Jan 22 00:00:00 1970 PST
5120   723 | 303 | 00723_update3      | Sat Jan 24 00:00:00 1970 PST
5121   724 |   4 | 00724              | Sun Jan 25 00:00:00 1970 PST
5122   726 |   6 | 00726              | Tue Jan 27 00:00:00 1970 PST
5123   727 | 407 | 00727_update7      | Wed Jan 28 00:00:00 1970 PST
5124   728 |   8 | 00728              | Thu Jan 29 00:00:00 1970 PST
5125   729 | 509 | 00729_update9      | Fri Jan 30 00:00:00 1970 PST
5126   730 |   0 | 00730              | Sat Jan 31 00:00:00 1970 PST
5127   731 |   1 | 00731              | Sun Feb 01 00:00:00 1970 PST
5128   733 | 303 | 00733_update3      | Tue Feb 03 00:00:00 1970 PST
5129   734 |   4 | 00734              | Wed Feb 04 00:00:00 1970 PST
5130   736 |   6 | 00736              | Fri Feb 06 00:00:00 1970 PST
5131   737 | 407 | 00737_update7      | Sat Feb 07 00:00:00 1970 PST
5132   738 |   8 | 00738              | Sun Feb 08 00:00:00 1970 PST
5133   739 | 509 | 00739_update9      | Mon Feb 09 00:00:00 1970 PST
5134   740 |   0 | 00740              | Tue Feb 10 00:00:00 1970 PST
5135   741 |   1 | 00741              | Wed Feb 11 00:00:00 1970 PST
5136   743 | 303 | 00743_update3      | Fri Feb 13 00:00:00 1970 PST
5137   744 |   4 | 00744              | Sat Feb 14 00:00:00 1970 PST
5138   746 |   6 | 00746              | Mon Feb 16 00:00:00 1970 PST
5139   747 | 407 | 00747_update7      | Tue Feb 17 00:00:00 1970 PST
5140   748 |   8 | 00748              | Wed Feb 18 00:00:00 1970 PST
5141   749 | 509 | 00749_update9      | Thu Feb 19 00:00:00 1970 PST
5142   750 |   0 | 00750              | Fri Feb 20 00:00:00 1970 PST
5143   751 |   1 | 00751              | Sat Feb 21 00:00:00 1970 PST
5144   753 | 303 | 00753_update3      | Mon Feb 23 00:00:00 1970 PST
5145   754 |   4 | 00754              | Tue Feb 24 00:00:00 1970 PST
5146   756 |   6 | 00756              | Thu Feb 26 00:00:00 1970 PST
5147   757 | 407 | 00757_update7      | Fri Feb 27 00:00:00 1970 PST
5148   758 |   8 | 00758              | Sat Feb 28 00:00:00 1970 PST
5149   759 | 509 | 00759_update9      | Sun Mar 01 00:00:00 1970 PST
5150   760 |   0 | 00760              | Mon Mar 02 00:00:00 1970 PST
5151   761 |   1 | 00761              | Tue Mar 03 00:00:00 1970 PST
5152   763 | 303 | 00763_update3      | Thu Mar 05 00:00:00 1970 PST
5153   764 |   4 | 00764              | Fri Mar 06 00:00:00 1970 PST
5154   766 |   6 | 00766              | Sun Mar 08 00:00:00 1970 PST
5155   767 | 407 | 00767_update7      | Mon Mar 09 00:00:00 1970 PST
5156   768 |   8 | 00768              | Tue Mar 10 00:00:00 1970 PST
5157   769 | 509 | 00769_update9      | Wed Mar 11 00:00:00 1970 PST
5158   770 |   0 | 00770              | Thu Mar 12 00:00:00 1970 PST
5159   771 |   1 | 00771              | Fri Mar 13 00:00:00 1970 PST
5160   773 | 303 | 00773_update3      | Sun Mar 15 00:00:00 1970 PST
5161   774 |   4 | 00774              | Mon Mar 16 00:00:00 1970 PST
5162   776 |   6 | 00776              | Wed Mar 18 00:00:00 1970 PST
5163   777 | 407 | 00777_update7      | Thu Mar 19 00:00:00 1970 PST
5164   778 |   8 | 00778              | Fri Mar 20 00:00:00 1970 PST
5165   779 | 509 | 00779_update9      | Sat Mar 21 00:00:00 1970 PST
5166   780 |   0 | 00780              | Sun Mar 22 00:00:00 1970 PST
5167   781 |   1 | 00781              | Mon Mar 23 00:00:00 1970 PST
5168   783 | 303 | 00783_update3      | Wed Mar 25 00:00:00 1970 PST
5169   784 |   4 | 00784              | Thu Mar 26 00:00:00 1970 PST
5170   786 |   6 | 00786              | Sat Mar 28 00:00:00 1970 PST
5171   787 | 407 | 00787_update7      | Sun Mar 29 00:00:00 1970 PST
5172   788 |   8 | 00788              | Mon Mar 30 00:00:00 1970 PST
5173   789 | 509 | 00789_update9      | Tue Mar 31 00:00:00 1970 PST
5174   790 |   0 | 00790              | Wed Apr 01 00:00:00 1970 PST
5175   791 |   1 | 00791              | Thu Apr 02 00:00:00 1970 PST
5176   793 | 303 | 00793_update3      | Sat Apr 04 00:00:00 1970 PST
5177   794 |   4 | 00794              | Sun Apr 05 00:00:00 1970 PST
5178   796 |   6 | 00796              | Tue Apr 07 00:00:00 1970 PST
5179   797 | 407 | 00797_update7      | Wed Apr 08 00:00:00 1970 PST
5180   798 |   8 | 00798              | Thu Apr 09 00:00:00 1970 PST
5181   799 | 509 | 00799_update9      | Fri Apr 10 00:00:00 1970 PST
5182   800 |   0 | 00800              | Thu Jan 01 00:00:00 1970 PST
5183   801 |   1 | 00801              | Fri Jan 02 00:00:00 1970 PST
5184   803 | 303 | 00803_update3      | Sun Jan 04 00:00:00 1970 PST
5185   804 |   4 | 00804              | Mon Jan 05 00:00:00 1970 PST
5186   806 |   6 | 00806              | Wed Jan 07 00:00:00 1970 PST
5187   807 | 407 | 00807_update7      | Thu Jan 08 00:00:00 1970 PST
5188   808 |   8 | 00808              | Fri Jan 09 00:00:00 1970 PST
5189   809 | 509 | 00809_update9      | Sat Jan 10 00:00:00 1970 PST
5190   810 |   0 | 00810              | Sun Jan 11 00:00:00 1970 PST
5191   811 |   1 | 00811              | Mon Jan 12 00:00:00 1970 PST
5192   813 | 303 | 00813_update3      | Wed Jan 14 00:00:00 1970 PST
5193   814 |   4 | 00814              | Thu Jan 15 00:00:00 1970 PST
5194   816 |   6 | 00816              | Sat Jan 17 00:00:00 1970 PST
5195   817 | 407 | 00817_update7      | Sun Jan 18 00:00:00 1970 PST
5196   818 |   8 | 00818              | Mon Jan 19 00:00:00 1970 PST
5197   819 | 509 | 00819_update9      | Tue Jan 20 00:00:00 1970 PST
5198   820 |   0 | 00820              | Wed Jan 21 00:00:00 1970 PST
5199   821 |   1 | 00821              | Thu Jan 22 00:00:00 1970 PST
5200   823 | 303 | 00823_update3      | Sat Jan 24 00:00:00 1970 PST
5201   824 |   4 | 00824              | Sun Jan 25 00:00:00 1970 PST
5202   826 |   6 | 00826              | Tue Jan 27 00:00:00 1970 PST
5203   827 | 407 | 00827_update7      | Wed Jan 28 00:00:00 1970 PST
5204   828 |   8 | 00828              | Thu Jan 29 00:00:00 1970 PST
5205   829 | 509 | 00829_update9      | Fri Jan 30 00:00:00 1970 PST
5206   830 |   0 | 00830              | Sat Jan 31 00:00:00 1970 PST
5207   831 |   1 | 00831              | Sun Feb 01 00:00:00 1970 PST
5208   833 | 303 | 00833_update3      | Tue Feb 03 00:00:00 1970 PST
5209   834 |   4 | 00834              | Wed Feb 04 00:00:00 1970 PST
5210   836 |   6 | 00836              | Fri Feb 06 00:00:00 1970 PST
5211   837 | 407 | 00837_update7      | Sat Feb 07 00:00:00 1970 PST
5212   838 |   8 | 00838              | Sun Feb 08 00:00:00 1970 PST
5213   839 | 509 | 00839_update9      | Mon Feb 09 00:00:00 1970 PST
5214   840 |   0 | 00840              | Tue Feb 10 00:00:00 1970 PST
5215   841 |   1 | 00841              | Wed Feb 11 00:00:00 1970 PST
5216   843 | 303 | 00843_update3      | Fri Feb 13 00:00:00 1970 PST
5217   844 |   4 | 00844              | Sat Feb 14 00:00:00 1970 PST
5218   846 |   6 | 00846              | Mon Feb 16 00:00:00 1970 PST
5219   847 | 407 | 00847_update7      | Tue Feb 17 00:00:00 1970 PST
5220   848 |   8 | 00848              | Wed Feb 18 00:00:00 1970 PST
5221   849 | 509 | 00849_update9      | Thu Feb 19 00:00:00 1970 PST
5222   850 |   0 | 00850              | Fri Feb 20 00:00:00 1970 PST
5223   851 |   1 | 00851              | Sat Feb 21 00:00:00 1970 PST
5224   853 | 303 | 00853_update3      | Mon Feb 23 00:00:00 1970 PST
5225   854 |   4 | 00854              | Tue Feb 24 00:00:00 1970 PST
5226   856 |   6 | 00856              | Thu Feb 26 00:00:00 1970 PST
5227   857 | 407 | 00857_update7      | Fri Feb 27 00:00:00 1970 PST
5228   858 |   8 | 00858              | Sat Feb 28 00:00:00 1970 PST
5229   859 | 509 | 00859_update9      | Sun Mar 01 00:00:00 1970 PST
5230   860 |   0 | 00860              | Mon Mar 02 00:00:00 1970 PST
5231   861 |   1 | 00861              | Tue Mar 03 00:00:00 1970 PST
5232   863 | 303 | 00863_update3      | Thu Mar 05 00:00:00 1970 PST
5233   864 |   4 | 00864              | Fri Mar 06 00:00:00 1970 PST
5234   866 |   6 | 00866              | Sun Mar 08 00:00:00 1970 PST
5235   867 | 407 | 00867_update7      | Mon Mar 09 00:00:00 1970 PST
5236   868 |   8 | 00868              | Tue Mar 10 00:00:00 1970 PST
5237   869 | 509 | 00869_update9      | Wed Mar 11 00:00:00 1970 PST
5238   870 |   0 | 00870              | Thu Mar 12 00:00:00 1970 PST
5239   871 |   1 | 00871              | Fri Mar 13 00:00:00 1970 PST
5240   873 | 303 | 00873_update3      | Sun Mar 15 00:00:00 1970 PST
5241   874 |   4 | 00874              | Mon Mar 16 00:00:00 1970 PST
5242   876 |   6 | 00876              | Wed Mar 18 00:00:00 1970 PST
5243   877 | 407 | 00877_update7      | Thu Mar 19 00:00:00 1970 PST
5244   878 |   8 | 00878              | Fri Mar 20 00:00:00 1970 PST
5245   879 | 509 | 00879_update9      | Sat Mar 21 00:00:00 1970 PST
5246   880 |   0 | 00880              | Sun Mar 22 00:00:00 1970 PST
5247   881 |   1 | 00881              | Mon Mar 23 00:00:00 1970 PST
5248   883 | 303 | 00883_update3      | Wed Mar 25 00:00:00 1970 PST
5249   884 |   4 | 00884              | Thu Mar 26 00:00:00 1970 PST
5250   886 |   6 | 00886              | Sat Mar 28 00:00:00 1970 PST
5251   887 | 407 | 00887_update7      | Sun Mar 29 00:00:00 1970 PST
5252   888 |   8 | 00888              | Mon Mar 30 00:00:00 1970 PST
5253   889 | 509 | 00889_update9      | Tue Mar 31 00:00:00 1970 PST
5254   890 |   0 | 00890              | Wed Apr 01 00:00:00 1970 PST
5255   891 |   1 | 00891              | Thu Apr 02 00:00:00 1970 PST
5256   893 | 303 | 00893_update3      | Sat Apr 04 00:00:00 1970 PST
5257   894 |   4 | 00894              | Sun Apr 05 00:00:00 1970 PST
5258   896 |   6 | 00896              | Tue Apr 07 00:00:00 1970 PST
5259   897 | 407 | 00897_update7      | Wed Apr 08 00:00:00 1970 PST
5260   898 |   8 | 00898              | Thu Apr 09 00:00:00 1970 PST
5261   899 | 509 | 00899_update9      | Fri Apr 10 00:00:00 1970 PST
5262   900 |   0 | 00900              | Thu Jan 01 00:00:00 1970 PST
5263   901 |   1 | 00901              | Fri Jan 02 00:00:00 1970 PST
5264   903 | 303 | 00903_update3      | Sun Jan 04 00:00:00 1970 PST
5265   904 |   4 | 00904              | Mon Jan 05 00:00:00 1970 PST
5266   906 |   6 | 00906              | Wed Jan 07 00:00:00 1970 PST
5267   907 | 407 | 00907_update7      | Thu Jan 08 00:00:00 1970 PST
5268   908 |   8 | 00908              | Fri Jan 09 00:00:00 1970 PST
5269   909 | 509 | 00909_update9      | Sat Jan 10 00:00:00 1970 PST
5270   910 |   0 | 00910              | Sun Jan 11 00:00:00 1970 PST
5271   911 |   1 | 00911              | Mon Jan 12 00:00:00 1970 PST
5272   913 | 303 | 00913_update3      | Wed Jan 14 00:00:00 1970 PST
5273   914 |   4 | 00914              | Thu Jan 15 00:00:00 1970 PST
5274   916 |   6 | 00916              | Sat Jan 17 00:00:00 1970 PST
5275   917 | 407 | 00917_update7      | Sun Jan 18 00:00:00 1970 PST
5276   918 |   8 | 00918              | Mon Jan 19 00:00:00 1970 PST
5277   919 | 509 | 00919_update9      | Tue Jan 20 00:00:00 1970 PST
5278   920 |   0 | 00920              | Wed Jan 21 00:00:00 1970 PST
5279   921 |   1 | 00921              | Thu Jan 22 00:00:00 1970 PST
5280   923 | 303 | 00923_update3      | Sat Jan 24 00:00:00 1970 PST
5281   924 |   4 | 00924              | Sun Jan 25 00:00:00 1970 PST
5282   926 |   6 | 00926              | Tue Jan 27 00:00:00 1970 PST
5283   927 | 407 | 00927_update7      | Wed Jan 28 00:00:00 1970 PST
5284   928 |   8 | 00928              | Thu Jan 29 00:00:00 1970 PST
5285   929 | 509 | 00929_update9      | Fri Jan 30 00:00:00 1970 PST
5286   930 |   0 | 00930              | Sat Jan 31 00:00:00 1970 PST
5287   931 |   1 | 00931              | Sun Feb 01 00:00:00 1970 PST
5288   933 | 303 | 00933_update3      | Tue Feb 03 00:00:00 1970 PST
5289   934 |   4 | 00934              | Wed Feb 04 00:00:00 1970 PST
5290   936 |   6 | 00936              | Fri Feb 06 00:00:00 1970 PST
5291   937 | 407 | 00937_update7      | Sat Feb 07 00:00:00 1970 PST
5292   938 |   8 | 00938              | Sun Feb 08 00:00:00 1970 PST
5293   939 | 509 | 00939_update9      | Mon Feb 09 00:00:00 1970 PST
5294   940 |   0 | 00940              | Tue Feb 10 00:00:00 1970 PST
5295   941 |   1 | 00941              | Wed Feb 11 00:00:00 1970 PST
5296   943 | 303 | 00943_update3      | Fri Feb 13 00:00:00 1970 PST
5297   944 |   4 | 00944              | Sat Feb 14 00:00:00 1970 PST
5298   946 |   6 | 00946              | Mon Feb 16 00:00:00 1970 PST
5299   947 | 407 | 00947_update7      | Tue Feb 17 00:00:00 1970 PST
5300   948 |   8 | 00948              | Wed Feb 18 00:00:00 1970 PST
5301   949 | 509 | 00949_update9      | Thu Feb 19 00:00:00 1970 PST
5302   950 |   0 | 00950              | Fri Feb 20 00:00:00 1970 PST
5303   951 |   1 | 00951              | Sat Feb 21 00:00:00 1970 PST
5304   953 | 303 | 00953_update3      | Mon Feb 23 00:00:00 1970 PST
5305   954 |   4 | 00954              | Tue Feb 24 00:00:00 1970 PST
5306   956 |   6 | 00956              | Thu Feb 26 00:00:00 1970 PST
5307   957 | 407 | 00957_update7      | Fri Feb 27 00:00:00 1970 PST
5308   958 |   8 | 00958              | Sat Feb 28 00:00:00 1970 PST
5309   959 | 509 | 00959_update9      | Sun Mar 01 00:00:00 1970 PST
5310   960 |   0 | 00960              | Mon Mar 02 00:00:00 1970 PST
5311   961 |   1 | 00961              | Tue Mar 03 00:00:00 1970 PST
5312   963 | 303 | 00963_update3      | Thu Mar 05 00:00:00 1970 PST
5313   964 |   4 | 00964              | Fri Mar 06 00:00:00 1970 PST
5314   966 |   6 | 00966              | Sun Mar 08 00:00:00 1970 PST
5315   967 | 407 | 00967_update7      | Mon Mar 09 00:00:00 1970 PST
5316   968 |   8 | 00968              | Tue Mar 10 00:00:00 1970 PST
5317   969 | 509 | 00969_update9      | Wed Mar 11 00:00:00 1970 PST
5318   970 |   0 | 00970              | Thu Mar 12 00:00:00 1970 PST
5319   971 |   1 | 00971              | Fri Mar 13 00:00:00 1970 PST
5320   973 | 303 | 00973_update3      | Sun Mar 15 00:00:00 1970 PST
5321   974 |   4 | 00974              | Mon Mar 16 00:00:00 1970 PST
5322   976 |   6 | 00976              | Wed Mar 18 00:00:00 1970 PST
5323   977 | 407 | 00977_update7      | Thu Mar 19 00:00:00 1970 PST
5324   978 |   8 | 00978              | Fri Mar 20 00:00:00 1970 PST
5325   979 | 509 | 00979_update9      | Sat Mar 21 00:00:00 1970 PST
5326   980 |   0 | 00980              | Sun Mar 22 00:00:00 1970 PST
5327   981 |   1 | 00981              | Mon Mar 23 00:00:00 1970 PST
5328   983 | 303 | 00983_update3      | Wed Mar 25 00:00:00 1970 PST
5329   984 |   4 | 00984              | Thu Mar 26 00:00:00 1970 PST
5330   986 |   6 | 00986              | Sat Mar 28 00:00:00 1970 PST
5331   987 | 407 | 00987_update7      | Sun Mar 29 00:00:00 1970 PST
5332   988 |   8 | 00988              | Mon Mar 30 00:00:00 1970 PST
5333   989 | 509 | 00989_update9      | Tue Mar 31 00:00:00 1970 PST
5334   990 |   0 | 00990              | Wed Apr 01 00:00:00 1970 PST
5335   991 |   1 | 00991              | Thu Apr 02 00:00:00 1970 PST
5336   993 | 303 | 00993_update3      | Sat Apr 04 00:00:00 1970 PST
5337   994 |   4 | 00994              | Sun Apr 05 00:00:00 1970 PST
5338   996 |   6 | 00996              | Tue Apr 07 00:00:00 1970 PST
5339   997 | 407 | 00997_update7      | Wed Apr 08 00:00:00 1970 PST
5340   998 |   8 | 00998              | Thu Apr 09 00:00:00 1970 PST
5341   999 | 509 | 00999_update9      | Fri Apr 10 00:00:00 1970 PST
5342  1000 |   0 | 01000              | Thu Jan 01 00:00:00 1970 PST
5343  1001 | 101 | 0000100001         | 
5344  1003 | 403 | 0000300003_update3 | 
5345  1004 | 104 | 0000400004         | 
5346  1006 | 106 | 0000600006         | 
5347  1007 | 507 | 0000700007_update7 | 
5348  1008 | 108 | 0000800008         | 
5349  1009 | 609 | 0000900009_update9 | 
5350  1010 | 100 | 0001000010         | 
5351  1011 | 101 | 0001100011         | 
5352  1013 | 403 | 0001300013_update3 | 
5353  1014 | 104 | 0001400014         | 
5354  1016 | 106 | 0001600016         | 
5355  1017 | 507 | 0001700017_update7 | 
5356  1018 | 108 | 0001800018         | 
5357  1019 | 609 | 0001900019_update9 | 
5358  1020 | 100 | 0002000020         | 
5359  1101 | 201 | aaa                | 
5360  1103 | 503 | ccc_update3        | 
5361  1104 | 204 | ddd                | 
5362 (819 rows)
5363
5364 EXPLAIN (verbose, costs off)
5365 INSERT INTO ft2 (c1,c2,c3) VALUES (9999,999,'foo') RETURNING tableoid::regclass;
5366                                                                                            QUERY PLAN                                                                                            
5367 -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5368  Insert on public.ft2
5369    Output: (tableoid)::regclass
5370    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)
5371    ->  Result
5372          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
5373 (5 rows)
5374
5375 INSERT INTO ft2 (c1,c2,c3) VALUES (9999,999,'foo') RETURNING tableoid::regclass;
5376  tableoid 
5377 ----------
5378  ft2
5379 (1 row)
5380
5381 EXPLAIN (verbose, costs off)
5382 UPDATE ft2 SET c3 = 'bar' WHERE c1 = 9999 RETURNING tableoid::regclass;             -- can be pushed down
5383                                      QUERY PLAN                                     
5384 ------------------------------------------------------------------------------------
5385  Update on public.ft2
5386    Output: (tableoid)::regclass
5387    ->  Foreign Update on public.ft2
5388          Remote SQL: UPDATE "S 1"."T 1" SET c3 = 'bar'::text WHERE (("C 1" = 9999))
5389 (4 rows)
5390
5391 UPDATE ft2 SET c3 = 'bar' WHERE c1 = 9999 RETURNING tableoid::regclass;
5392  tableoid 
5393 ----------
5394  ft2
5395 (1 row)
5396
5397 EXPLAIN (verbose, costs off)
5398 DELETE FROM ft2 WHERE c1 = 9999 RETURNING tableoid::regclass;                       -- can be pushed down
5399                              QUERY PLAN                             
5400 --------------------------------------------------------------------
5401  Delete on public.ft2
5402    Output: (tableoid)::regclass
5403    ->  Foreign Delete on public.ft2
5404          Remote SQL: DELETE FROM "S 1"."T 1" WHERE (("C 1" = 9999))
5405 (4 rows)
5406
5407 DELETE FROM ft2 WHERE c1 = 9999 RETURNING tableoid::regclass;
5408  tableoid 
5409 ----------
5410  ft2
5411 (1 row)
5412
5413 -- Test UPDATE/DELETE with RETURNING on a three-table join
5414 INSERT INTO ft2 (c1,c2,c3)
5415   SELECT id, id - 1200, to_char(id, 'FM00000') FROM generate_series(1201, 1300) id;
5416 EXPLAIN (verbose, costs off)
5417 UPDATE ft2 SET c3 = 'foo'
5418   FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
5419   WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
5420   RETURNING ft2, ft2.*, ft4, ft4.*;       -- can be pushed down
5421                                                                                                                                                                           QUERY PLAN                                                                                                                                                                           
5422 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5423  Update on public.ft2
5424    Output: ft2.*, ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.*, ft4.c1, ft4.c2, ft4.c3
5425    ->  Foreign Update
5426          Remote SQL: UPDATE "S 1"."T 1" r1 SET c3 = 'foo'::text FROM ("S 1"."T 3" r2 INNER JOIN "S 1"."T 4" r3 ON (TRUE)) WHERE ((r2.c1 = r3.c1)) AND ((r1.c2 = r2.c1)) AND ((r1."C 1" > 1200)) RETURNING r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c7, r1.c8, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2.c1, r2.c2, r2.c3) END, r2.c1, r2.c2, r2.c3
5427 (4 rows)
5428
5429 UPDATE ft2 SET c3 = 'foo'
5430   FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
5431   WHERE ft2.c1 > 1200 AND ft2.c2 = ft4.c1
5432   RETURNING ft2, ft2.*, ft4, ft4.*;
5433               ft2               |  c1  | c2 | c3  | c4 | c5 | c6 |     c7     | c8 |      ft4       | c1 | c2 |   c3   
5434 --------------------------------+------+----+-----+----+----+----+------------+----+----------------+----+----+--------
5435  (1206,6,foo,,,,"ft2       ",)  | 1206 |  6 | foo |    |    |    | ft2        |    | (6,7,AAA006)   |  6 |  7 | AAA006
5436  (1212,12,foo,,,,"ft2       ",) | 1212 | 12 | foo |    |    |    | ft2        |    | (12,13,AAA012) | 12 | 13 | AAA012
5437  (1218,18,foo,,,,"ft2       ",) | 1218 | 18 | foo |    |    |    | ft2        |    | (18,19,AAA018) | 18 | 19 | AAA018
5438  (1224,24,foo,,,,"ft2       ",) | 1224 | 24 | foo |    |    |    | ft2        |    | (24,25,AAA024) | 24 | 25 | AAA024
5439  (1230,30,foo,,,,"ft2       ",) | 1230 | 30 | foo |    |    |    | ft2        |    | (30,31,AAA030) | 30 | 31 | AAA030
5440  (1236,36,foo,,,,"ft2       ",) | 1236 | 36 | foo |    |    |    | ft2        |    | (36,37,AAA036) | 36 | 37 | AAA036
5441  (1242,42,foo,,,,"ft2       ",) | 1242 | 42 | foo |    |    |    | ft2        |    | (42,43,AAA042) | 42 | 43 | AAA042
5442  (1248,48,foo,,,,"ft2       ",) | 1248 | 48 | foo |    |    |    | ft2        |    | (48,49,AAA048) | 48 | 49 | AAA048
5443  (1254,54,foo,,,,"ft2       ",) | 1254 | 54 | foo |    |    |    | ft2        |    | (54,55,AAA054) | 54 | 55 | AAA054
5444  (1260,60,foo,,,,"ft2       ",) | 1260 | 60 | foo |    |    |    | ft2        |    | (60,61,AAA060) | 60 | 61 | AAA060
5445  (1266,66,foo,,,,"ft2       ",) | 1266 | 66 | foo |    |    |    | ft2        |    | (66,67,AAA066) | 66 | 67 | AAA066
5446  (1272,72,foo,,,,"ft2       ",) | 1272 | 72 | foo |    |    |    | ft2        |    | (72,73,AAA072) | 72 | 73 | AAA072
5447  (1278,78,foo,,,,"ft2       ",) | 1278 | 78 | foo |    |    |    | ft2        |    | (78,79,AAA078) | 78 | 79 | AAA078
5448  (1284,84,foo,,,,"ft2       ",) | 1284 | 84 | foo |    |    |    | ft2        |    | (84,85,AAA084) | 84 | 85 | AAA084
5449  (1290,90,foo,,,,"ft2       ",) | 1290 | 90 | foo |    |    |    | ft2        |    | (90,91,AAA090) | 90 | 91 | AAA090
5450  (1296,96,foo,,,,"ft2       ",) | 1296 | 96 | foo |    |    |    | ft2        |    | (96,97,AAA096) | 96 | 97 | AAA096
5451 (16 rows)
5452
5453 EXPLAIN (verbose, costs off)
5454 DELETE FROM ft2
5455   USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1)
5456   WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1
5457   RETURNING 100;                          -- can be pushed down
5458                                                                                             QUERY PLAN                                                                                             
5459 ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5460  Delete on public.ft2
5461    Output: 100
5462    ->  Foreign Delete
5463          Remote SQL: DELETE FROM "S 1"."T 1" r1 USING ("S 1"."T 3" r2 LEFT JOIN "S 1"."T 4" r3 ON (((r2.c1 = r3.c1)))) WHERE ((r1.c2 = r2.c1)) AND ((r1."C 1" > 1200)) AND (((r1."C 1" % 10) = 0))
5464 (4 rows)
5465
5466 DELETE FROM ft2
5467   USING ft4 LEFT JOIN ft5 ON (ft4.c1 = ft5.c1)
5468   WHERE ft2.c1 > 1200 AND ft2.c1 % 10 = 0 AND ft2.c2 = ft4.c1
5469   RETURNING 100;
5470  ?column? 
5471 ----------
5472       100
5473       100
5474       100
5475       100
5476       100
5477       100
5478       100
5479       100
5480       100
5481       100
5482 (10 rows)
5483
5484 DELETE FROM ft2 WHERE ft2.c1 > 1200;
5485 -- Test UPDATE/DELETE with WHERE or JOIN/ON conditions containing
5486 -- user-defined operators/functions
5487 ALTER SERVER loopback OPTIONS (DROP extensions);
5488 INSERT INTO ft2 (c1,c2,c3)
5489   SELECT id, id % 10, to_char(id, 'FM00000') FROM generate_series(2001, 2010) id;
5490 EXPLAIN (verbose, costs off)
5491 UPDATE ft2 SET c3 = 'bar' WHERE postgres_fdw_abs(c1) > 2000 RETURNING *;            -- can't be pushed down
5492                                                 QUERY PLAN                                                
5493 ----------------------------------------------------------------------------------------------------------
5494  Update on public.ft2
5495    Output: c1, c2, c3, c4, c5, c6, c7, c8
5496    Remote SQL: UPDATE "S 1"."T 1" SET c3 = $2 WHERE ctid = $1 RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8
5497    ->  Foreign Scan on public.ft2
5498          Output: c1, c2, NULL::integer, 'bar'::text, c4, c5, c6, c7, c8, ctid
5499          Filter: (postgres_fdw_abs(ft2.c1) > 2000)
5500          Remote SQL: SELECT "C 1", c2, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" FOR UPDATE
5501 (7 rows)
5502
5503 UPDATE ft2 SET c3 = 'bar' WHERE postgres_fdw_abs(c1) > 2000 RETURNING *;
5504   c1  | c2 | c3  | c4 | c5 | c6 |     c7     | c8 
5505 ------+----+-----+----+----+----+------------+----
5506  2001 |  1 | bar |    |    |    | ft2        | 
5507  2002 |  2 | bar |    |    |    | ft2        | 
5508  2003 |  3 | bar |    |    |    | ft2        | 
5509  2004 |  4 | bar |    |    |    | ft2        | 
5510  2005 |  5 | bar |    |    |    | ft2        | 
5511  2006 |  6 | bar |    |    |    | ft2        | 
5512  2007 |  7 | bar |    |    |    | ft2        | 
5513  2008 |  8 | bar |    |    |    | ft2        | 
5514  2009 |  9 | bar |    |    |    | ft2        | 
5515  2010 |  0 | bar |    |    |    | ft2        | 
5516 (10 rows)
5517
5518 EXPLAIN (verbose, costs off)
5519 UPDATE ft2 SET c3 = 'baz'
5520   FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
5521   WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1
5522   RETURNING ft2.*, ft4.*, ft5.*;                                                    -- can't be pushed down
5523                                                                                                                                           QUERY PLAN                                                                                                                                          
5524 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5525  Update on public.ft2
5526    Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3
5527    Remote SQL: UPDATE "S 1"."T 1" SET c3 = $2 WHERE ctid = $1 RETURNING "C 1", c2, c3, c4, c5, c6, c7, c8
5528    ->  Nested Loop
5529          Output: ft2.c1, ft2.c2, NULL::integer, 'baz'::text, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.ctid, ft4.*, ft5.*, ft4.c1, ft4.c2, ft4.c3, ft5.c1, ft5.c2, ft5.c3
5530          Join Filter: (ft2.c2 === ft4.c1)
5531          ->  Foreign Scan on public.ft2
5532                Output: ft2.c1, ft2.c2, ft2.c4, ft2.c5, ft2.c6, ft2.c7, ft2.c8, ft2.ctid
5533                Remote SQL: SELECT "C 1", c2, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1" WHERE (("C 1" > 2000)) FOR UPDATE
5534          ->  Foreign Scan
5535                Output: ft4.*, ft4.c1, ft4.c2, ft4.c3, ft5.*, ft5.c1, ft5.c2, ft5.c3
5536                Relations: (public.ft4) INNER JOIN (public.ft5)
5537                Remote SQL: SELECT CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2.c1, r2.c2, r2.c3) END, r2.c1, r2.c2, r2.c3, CASE WHEN (r3.*)::text IS NOT NULL THEN ROW(r3.c1, r3.c2, r3.c3) END, r3.c1, r3.c2, r3.c3 FROM ("S 1"."T 3" r2 INNER JOIN "S 1"."T 4" r3 ON (((r2.c1 = r3.c1))))
5538                ->  Hash Join
5539                      Output: ft4.*, ft4.c1, ft4.c2, ft4.c3, ft5.*, ft5.c1, ft5.c2, ft5.c3
5540                      Hash Cond: (ft4.c1 = ft5.c1)
5541                      ->  Foreign Scan on public.ft4
5542                            Output: ft4.*, ft4.c1, ft4.c2, ft4.c3
5543                            Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
5544                      ->  Hash
5545                            Output: ft5.*, ft5.c1, ft5.c2, ft5.c3
5546                            ->  Foreign Scan on public.ft5
5547                                  Output: ft5.*, ft5.c1, ft5.c2, ft5.c3
5548                                  Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4"
5549 (24 rows)
5550
5551 UPDATE ft2 SET c3 = 'baz'
5552   FROM ft4 INNER JOIN ft5 ON (ft4.c1 = ft5.c1)
5553   WHERE ft2.c1 > 2000 AND ft2.c2 === ft4.c1
5554   RETURNING ft2.*, ft4.*, ft5.*;
5555   c1  | c2 | c3  | c4 | c5 | c6 |     c7     | c8 | c1 | c2 |   c3   | c1 | c2 |   c3   
5556 ------+----+-----+----+----+----+------------+----+----+----+--------+----+----+--------
5557  2006 |  6 | baz |    |    |    | ft2        |    |  6 |  7 | AAA006 |  6 |  7 | AAA006
5558 (1 row)
5559
5560 EXPLAIN (verbose, costs off)
5561 DELETE FROM ft2
5562   USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1)
5563   WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1
5564   RETURNING ft2.c1, ft2.c2, ft2.c3;       -- can't be pushed down
5565                                                                                                                                                                      QUERY PLAN                                                                                                                                                                     
5566 ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
5567  Delete on public.ft2
5568    Output: ft2.c1, ft2.c2, ft2.c3
5569    Remote SQL: DELETE FROM "S 1"."T 1" WHERE ctid = $1 RETURNING "C 1", c2, c3
5570    ->  Foreign Scan
5571          Output: ft2.ctid, ft4.*, ft5.*
5572          Filter: (ft4.c1 === ft5.c1)
5573          Relations: ((public.ft2) INNER JOIN (public.ft4)) INNER JOIN (public.ft5)
5574          Remote SQL: SELECT r1.ctid, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2.c1, r2.c2, r2.c3) END, CASE WHEN (r3.*)::text IS NOT NULL THEN ROW(r3.c1, r3.c2, r3.c3) END, r2.c1, r3.c1 FROM (("S 1"."T 1" r1 INNER JOIN "S 1"."T 3" r2 ON (((r1.c2 = r2.c1)) AND ((r1."C 1" > 2000)))) INNER JOIN "S 1"."T 4" r3 ON (TRUE)) FOR UPDATE OF r1
5575          ->  Nested Loop
5576                Output: ft2.ctid, ft4.*, ft5.*, ft4.c1, ft5.c1
5577                ->  Nested Loop
5578                      Output: ft2.ctid, ft4.*, ft4.c1
5579                      Join Filter: (ft2.c2 = ft4.c1)
5580                      ->  Foreign Scan on public.ft2
5581                            Output: ft2.ctid, ft2.c2
5582                            Remote SQL: SELECT c2, ctid FROM "S 1"."T 1" WHERE (("C 1" > 2000)) FOR UPDATE
5583                      ->  Foreign Scan on public.ft4
5584                            Output: ft4.*, ft4.c1
5585                            Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 3"
5586                ->  Foreign Scan on public.ft5
5587                      Output: ft5.*, ft5.c1
5588                      Remote SQL: SELECT c1, c2, c3 FROM "S 1"."T 4"
5589 (22 rows)
5590
5591 DELETE FROM ft2
5592   USING ft4 INNER JOIN ft5 ON (ft4.c1 === ft5.c1)
5593   WHERE ft2.c1 > 2000 AND ft2.c2 = ft4.c1
5594   RETURNING ft2.c1, ft2.c2, ft2.c3;
5595   c1  | c2 | c3  
5596 ------+----+-----
5597  2006 |  6 | baz
5598 (1 row)
5599
5600 DELETE FROM ft2 WHERE ft2.c1 > 2000;
5601 ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
5602 -- Test that trigger on remote table works as expected
5603 CREATE OR REPLACE FUNCTION "S 1".F_BRTRIG() RETURNS trigger AS $$
5604 BEGIN
5605     NEW.c3 = NEW.c3 || '_trig_update';
5606     RETURN NEW;
5607 END;
5608 $$ LANGUAGE plpgsql;
5609 CREATE TRIGGER t1_br_insert BEFORE INSERT OR UPDATE
5610     ON "S 1"."T 1" FOR EACH ROW EXECUTE PROCEDURE "S 1".F_BRTRIG();
5611 INSERT INTO ft2 (c1,c2,c3) VALUES (1208, 818, 'fff') RETURNING *;
5612   c1  | c2  |       c3        | c4 | c5 | c6 |     c7     | c8 
5613 ------+-----+-----------------+----+----+----+------------+----
5614  1208 | 818 | fff_trig_update |    |    |    | ft2        | 
5615 (1 row)
5616
5617 INSERT INTO ft2 (c1,c2,c3,c6) VALUES (1218, 818, 'ggg', '(--;') RETURNING *;
5618   c1  | c2  |       c3        | c4 | c5 |  c6  |     c7     | c8 
5619 ------+-----+-----------------+----+----+------+------------+----
5620  1218 | 818 | ggg_trig_update |    |    | (--; | ft2        | 
5621 (1 row)
5622
5623 UPDATE ft2 SET c2 = c2 + 600 WHERE c1 % 10 = 8 AND c1 < 1200 RETURNING *;
5624   c1  | c2  |           c3           |              c4              |            c5            | c6 |     c7     | c8  
5625 ------+-----+------------------------+------------------------------+--------------------------+----+------------+-----
5626     8 | 608 | 00008_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
5627    18 | 608 | 00018_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
5628    28 | 608 | 00028_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
5629    38 | 608 | 00038_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
5630    48 | 608 | 00048_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
5631    58 | 608 | 00058_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
5632    68 | 608 | 00068_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
5633    78 | 608 | 00078_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
5634    88 | 608 | 00088_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
5635    98 | 608 | 00098_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
5636   108 | 608 | 00108_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
5637   118 | 608 | 00118_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
5638   128 | 608 | 00128_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
5639   138 | 608 | 00138_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
5640   148 | 608 | 00148_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
5641   158 | 608 | 00158_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
5642   168 | 608 | 00168_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
5643   178 | 608 | 00178_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
5644   188 | 608 | 00188_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
5645   198 | 608 | 00198_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
5646   208 | 608 | 00208_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
5647   218 | 608 | 00218_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
5648   228 | 608 | 00228_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
5649   238 | 608 | 00238_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
5650   248 | 608 | 00248_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
5651   258 | 608 | 00258_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
5652   268 | 608 | 00268_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
5653   278 | 608 | 00278_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
5654   288 | 608 | 00288_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
5655   298 | 608 | 00298_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
5656   308 | 608 | 00308_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
5657   318 | 608 | 00318_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
5658   328 | 608 | 00328_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
5659   338 | 608 | 00338_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
5660   348 | 608 | 00348_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
5661   358 | 608 | 00358_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
5662   368 | 608 | 00368_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
5663   378 | 608 | 00378_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
5664   388 | 608 | 00388_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
5665   398 | 608 | 00398_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
5666   408 | 608 | 00408_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
5667   418 | 608 | 00418_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
5668   428 | 608 | 00428_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
5669   438 | 608 | 00438_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
5670   448 | 608 | 00448_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
5671   458 | 608 | 00458_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
5672   468 | 608 | 00468_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
5673   478 | 608 | 00478_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
5674   488 | 608 | 00488_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
5675   498 | 608 | 00498_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
5676   508 | 608 | 00508_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
5677   518 | 608 | 00518_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
5678   528 | 608 | 00528_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
5679   538 | 608 | 00538_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
5680   548 | 608 | 00548_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
5681   558 | 608 | 00558_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
5682   568 | 608 | 00568_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
5683   578 | 608 | 00578_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
5684   588 | 608 | 00588_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
5685   598 | 608 | 00598_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
5686   608 | 608 | 00608_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
5687   618 | 608 | 00618_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
5688   628 | 608 | 00628_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
5689   638 | 608 | 00638_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
5690   648 | 608 | 00648_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
5691   658 | 608 | 00658_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
5692   668 | 608 | 00668_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
5693   678 | 608 | 00678_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
5694   688 | 608 | 00688_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
5695   698 | 608 | 00698_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
5696   708 | 608 | 00708_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
5697   718 | 608 | 00718_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
5698   728 | 608 | 00728_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
5699   738 | 608 | 00738_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
5700   748 | 608 | 00748_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
5701   758 | 608 | 00758_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
5702   768 | 608 | 00768_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
5703   778 | 608 | 00778_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
5704   788 | 608 | 00788_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
5705   798 | 608 | 00798_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
5706   808 | 608 | 00808_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
5707   818 | 608 | 00818_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
5708   828 | 608 | 00828_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
5709   838 | 608 | 00838_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
5710   848 | 608 | 00848_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
5711   858 | 608 | 00858_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
5712   868 | 608 | 00868_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
5713   878 | 608 | 00878_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
5714   888 | 608 | 00888_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
5715   898 | 608 | 00898_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
5716   908 | 608 | 00908_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
5717   918 | 608 | 00918_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
5718   928 | 608 | 00928_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
5719   938 | 608 | 00938_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
5720   948 | 608 | 00948_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
5721   958 | 608 | 00958_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
5722   968 | 608 | 00968_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
5723   978 | 608 | 00978_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
5724   988 | 608 | 00988_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
5725   998 | 608 | 00998_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
5726  1008 | 708 | 0000800008_trig_update |                              |                          |    | ft2        | 
5727  1018 | 708 | 0001800018_trig_update |                              |                          |    | ft2        | 
5728 (102 rows)
5729
5730 -- Test errors thrown on remote side during update
5731 ALTER TABLE "S 1"."T 1" ADD CONSTRAINT c2positive CHECK (c2 >= 0);
5732 INSERT INTO ft1(c1, c2) VALUES(11, 12);  -- duplicate key
5733 ERROR:  duplicate key value violates unique constraint "t1_pkey"
5734 DETAIL:  Key ("C 1")=(11) already exists.
5735 CONTEXT:  Remote SQL command: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
5736 INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT DO NOTHING; -- works
5737 INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO NOTHING; -- unsupported
5738 ERROR:  there is no unique or exclusion constraint matching the ON CONFLICT specification
5739 INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO UPDATE SET c3 = 'ffg'; -- unsupported
5740 ERROR:  there is no unique or exclusion constraint matching the ON CONFLICT specification
5741 INSERT INTO ft1(c1, c2) VALUES(1111, -2);  -- c2positive
5742 ERROR:  new row for relation "T 1" violates check constraint "c2positive"
5743 DETAIL:  Failing row contains (1111, -2, null, null, null, null, ft1       , null).
5744 CONTEXT:  Remote SQL command: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
5745 UPDATE ft1 SET c2 = -c2 WHERE c1 = 1;  -- c2positive
5746 ERROR:  new row for relation "T 1" violates check constraint "c2positive"
5747 DETAIL:  Failing row contains (1, -1, 00001_trig_update, 1970-01-02 08:00:00+00, 1970-01-02 00:00:00, 1, 1         , foo).
5748 CONTEXT:  Remote SQL command: UPDATE "S 1"."T 1" SET c2 = (- c2) WHERE (("C 1" = 1))
5749 -- Test savepoint/rollback behavior
5750 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
5751  c2  | count 
5752 -----+-------
5753    0 |   100
5754    1 |   100
5755    4 |   100
5756    6 |   100
5757  100 |     2
5758  101 |     2
5759  104 |     2
5760  106 |     2
5761  201 |     1
5762  204 |     1
5763  303 |   100
5764  403 |     2
5765  407 |   100
5766 (13 rows)
5767
5768 select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
5769  c2  | count 
5770 -----+-------
5771    0 |   100
5772    1 |   100
5773    4 |   100
5774    6 |   100
5775  100 |     2
5776  101 |     2
5777  104 |     2
5778  106 |     2
5779  201 |     1
5780  204 |     1
5781  303 |   100
5782  403 |     2
5783  407 |   100
5784 (13 rows)
5785
5786 begin;
5787 update ft2 set c2 = 42 where c2 = 0;
5788 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
5789  c2  | count 
5790 -----+-------
5791    1 |   100
5792    4 |   100
5793    6 |   100
5794   42 |   100
5795  100 |     2
5796  101 |     2
5797  104 |     2
5798  106 |     2
5799  201 |     1
5800  204 |     1
5801  303 |   100
5802  403 |     2
5803  407 |   100
5804 (13 rows)
5805
5806 savepoint s1;
5807 update ft2 set c2 = 44 where c2 = 4;
5808 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
5809  c2  | count 
5810 -----+-------
5811    1 |   100
5812    6 |   100
5813   42 |   100
5814   44 |   100
5815  100 |     2
5816  101 |     2
5817  104 |     2
5818  106 |     2
5819  201 |     1
5820  204 |     1
5821  303 |   100
5822  403 |     2
5823  407 |   100
5824 (13 rows)
5825
5826 release savepoint s1;
5827 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
5828  c2  | count 
5829 -----+-------
5830    1 |   100
5831    6 |   100
5832   42 |   100
5833   44 |   100
5834  100 |     2
5835  101 |     2
5836  104 |     2
5837  106 |     2
5838  201 |     1
5839  204 |     1
5840  303 |   100
5841  403 |     2
5842  407 |   100
5843 (13 rows)
5844
5845 savepoint s2;
5846 update ft2 set c2 = 46 where c2 = 6;
5847 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
5848  c2  | count 
5849 -----+-------
5850    1 |   100
5851   42 |   100
5852   44 |   100
5853   46 |   100
5854  100 |     2
5855  101 |     2
5856  104 |     2
5857  106 |     2
5858  201 |     1
5859  204 |     1
5860  303 |   100
5861  403 |     2
5862  407 |   100
5863 (13 rows)
5864
5865 rollback to savepoint s2;
5866 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
5867  c2  | count 
5868 -----+-------
5869    1 |   100
5870    6 |   100
5871   42 |   100
5872   44 |   100
5873  100 |     2
5874  101 |     2
5875  104 |     2
5876  106 |     2
5877  201 |     1
5878  204 |     1
5879  303 |   100
5880  403 |     2
5881  407 |   100
5882 (13 rows)
5883
5884 release savepoint s2;
5885 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
5886  c2  | count 
5887 -----+-------
5888    1 |   100
5889    6 |   100
5890   42 |   100
5891   44 |   100
5892  100 |     2
5893  101 |     2
5894  104 |     2
5895  106 |     2
5896  201 |     1
5897  204 |     1
5898  303 |   100
5899  403 |     2
5900  407 |   100
5901 (13 rows)
5902
5903 savepoint s3;
5904 update ft2 set c2 = -2 where c2 = 42 and c1 = 10; -- fail on remote side
5905 ERROR:  new row for relation "T 1" violates check constraint "c2positive"
5906 DETAIL:  Failing row contains (10, -2, 00010_trig_update_trig_update, 1970-01-11 08:00:00+00, 1970-01-11 00:00:00, 0, 0         , foo).
5907 CONTEXT:  Remote SQL command: UPDATE "S 1"."T 1" SET c2 = (-2) WHERE ((c2 = 42)) AND (("C 1" = 10))
5908 rollback to savepoint s3;
5909 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
5910  c2  | count 
5911 -----+-------
5912    1 |   100
5913    6 |   100
5914   42 |   100
5915   44 |   100
5916  100 |     2
5917  101 |     2
5918  104 |     2
5919  106 |     2
5920  201 |     1
5921  204 |     1
5922  303 |   100
5923  403 |     2
5924  407 |   100
5925 (13 rows)
5926
5927 release savepoint s3;
5928 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
5929  c2  | count 
5930 -----+-------
5931    1 |   100
5932    6 |   100
5933   42 |   100
5934   44 |   100
5935  100 |     2
5936  101 |     2
5937  104 |     2
5938  106 |     2
5939  201 |     1
5940  204 |     1
5941  303 |   100
5942  403 |     2
5943  407 |   100
5944 (13 rows)
5945
5946 -- none of the above is committed yet remotely
5947 select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
5948  c2  | count 
5949 -----+-------
5950    0 |   100
5951    1 |   100
5952    4 |   100
5953    6 |   100
5954  100 |     2
5955  101 |     2
5956  104 |     2
5957  106 |     2
5958  201 |     1
5959  204 |     1
5960  303 |   100
5961  403 |     2
5962  407 |   100
5963 (13 rows)
5964
5965 commit;
5966 select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
5967  c2  | count 
5968 -----+-------
5969    1 |   100
5970    6 |   100
5971   42 |   100
5972   44 |   100
5973  100 |     2
5974  101 |     2
5975  104 |     2
5976  106 |     2
5977  201 |     1
5978  204 |     1
5979  303 |   100
5980  403 |     2
5981  407 |   100
5982 (13 rows)
5983
5984 select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
5985  c2  | count 
5986 -----+-------
5987    1 |   100
5988    6 |   100
5989   42 |   100
5990   44 |   100
5991  100 |     2
5992  101 |     2
5993  104 |     2
5994  106 |     2
5995  201 |     1
5996  204 |     1
5997  303 |   100
5998  403 |     2
5999  407 |   100
6000 (13 rows)
6001
6002 -- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs
6003 -- FIRST behavior here.
6004 -- ORDER BY DESC NULLS LAST options
6005 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10;
6006                                                            QUERY PLAN                                                            
6007 ---------------------------------------------------------------------------------------------------------------------------------
6008  Limit
6009    Output: c1, c2, c3, c4, c5, c6, c7, c8
6010    ->  Foreign Scan on public.ft1
6011          Output: c1, c2, c3, c4, c5, c6, c7, c8
6012          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
6013 (5 rows)
6014
6015 SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795  LIMIT 10;
6016   c1  | c2  |         c3         |              c4              |            c5            |  c6  |     c7     | c8  
6017 ------+-----+--------------------+------------------------------+--------------------------+------+------------+-----
6018   960 |  42 | 00960_trig_update  | Mon Mar 02 00:00:00 1970 PST | Mon Mar 02 00:00:00 1970 | 0    | 0          | foo
6019   970 |  42 | 00970_trig_update  | Thu Mar 12 00:00:00 1970 PST | Thu Mar 12 00:00:00 1970 | 0    | 0          | foo
6020   980 |  42 | 00980_trig_update  | Sun Mar 22 00:00:00 1970 PST | Sun Mar 22 00:00:00 1970 | 0    | 0          | foo
6021   990 |  42 | 00990_trig_update  | Wed Apr 01 00:00:00 1970 PST | Wed Apr 01 00:00:00 1970 | 0    | 0          | foo
6022  1000 |  42 | 01000_trig_update  | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0    | 0          | foo
6023  1218 | 818 | ggg_trig_update    |                              |                          | (--; | ft2        | 
6024  1001 | 101 | 0000100001         |                              |                          |      | ft2        | 
6025  1003 | 403 | 0000300003_update3 |                              |                          |      | ft2        | 
6026  1004 | 104 | 0000400004         |                              |                          |      | ft2        | 
6027  1006 | 106 | 0000600006         |                              |                          |      | ft2        | 
6028 (10 rows)
6029
6030 -- ORDER BY DESC NULLS FIRST options
6031 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
6032                                                             QUERY PLAN                                                            
6033 ----------------------------------------------------------------------------------------------------------------------------------
6034  Limit
6035    Output: c1, c2, c3, c4, c5, c6, c7, c8
6036    ->  Foreign Scan on public.ft1
6037          Output: c1, c2, c3, c4, c5, c6, c7, c8
6038          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
6039 (5 rows)
6040
6041 SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
6042   c1  | c2  |       c3        |              c4              |            c5            | c6 |     c7     | c8  
6043 ------+-----+-----------------+------------------------------+--------------------------+----+------------+-----
6044  1020 | 100 | 0002000020      |                              |                          |    | ft2        | 
6045  1101 | 201 | aaa             |                              |                          |    | ft2        | 
6046  1103 | 503 | ccc_update3     |                              |                          |    | ft2        | 
6047  1104 | 204 | ddd             |                              |                          |    | ft2        | 
6048  1208 | 818 | fff_trig_update |                              |                          |    | ft2        | 
6049     9 | 509 | 00009_update9   | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | ft2        | foo
6050    19 | 509 | 00019_update9   | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9  | ft2        | foo
6051    29 | 509 | 00029_update9   | Fri Jan 30 00:00:00 1970 PST | Fri Jan 30 00:00:00 1970 | 9  | ft2        | foo
6052    39 | 509 | 00039_update9   | Mon Feb 09 00:00:00 1970 PST | Mon Feb 09 00:00:00 1970 | 9  | ft2        | foo
6053    49 | 509 | 00049_update9   | Thu Feb 19 00:00:00 1970 PST | Thu Feb 19 00:00:00 1970 | 9  | ft2        | foo
6054 (10 rows)
6055
6056 -- ORDER BY ASC NULLS FIRST options
6057 EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
6058                                                            QUERY PLAN                                                            
6059 ---------------------------------------------------------------------------------------------------------------------------------
6060  Limit
6061    Output: c1, c2, c3, c4, c5, c6, c7, c8
6062    ->  Foreign Scan on public.ft1
6063          Output: c1, c2, c3, c4, c5, c6, c7, c8
6064          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
6065 (5 rows)
6066
6067 SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
6068   c1  | c2  |        c3         |              c4              |            c5            |  c6  |     c7     | c8  
6069 ------+-----+-------------------+------------------------------+--------------------------+------+------------+-----
6070  1020 | 100 | 0002000020        |                              |                          |      | ft2        | 
6071  1101 | 201 | aaa               |                              |                          |      | ft2        | 
6072  1103 | 503 | ccc_update3       |                              |                          |      | ft2        | 
6073  1104 | 204 | ddd               |                              |                          |      | ft2        | 
6074  1208 | 818 | fff_trig_update   |                              |                          |      | ft2        | 
6075  1218 | 818 | ggg_trig_update   |                              |                          | (--; | ft2        | 
6076    10 |  42 | 00010_trig_update | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0    | 0          | foo
6077    20 |  42 | 00020_trig_update | Wed Jan 21 00:00:00 1970 PST | Wed Jan 21 00:00:00 1970 | 0    | 0          | foo
6078    30 |  42 | 00030_trig_update | Sat Jan 31 00:00:00 1970 PST | Sat Jan 31 00:00:00 1970 | 0    | 0          | foo
6079    40 |  42 | 00040_trig_update | Tue Feb 10 00:00:00 1970 PST | Tue Feb 10 00:00:00 1970 | 0    | 0          | foo
6080 (10 rows)
6081
6082 -- ===================================================================
6083 -- test check constraints
6084 -- ===================================================================
6085 -- Consistent check constraints provide consistent results
6086 ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK (c2 >= 0);
6087 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0;
6088                            QUERY PLAN                            
6089 -----------------------------------------------------------------
6090  Foreign Scan
6091    Output: (count(*))
6092    Relations: Aggregate on (public.ft1)
6093    Remote SQL: SELECT count(*) FROM "S 1"."T 1" WHERE ((c2 < 0))
6094 (4 rows)
6095
6096 SELECT count(*) FROM ft1 WHERE c2 < 0;
6097  count 
6098 -------
6099      0
6100 (1 row)
6101
6102 SET constraint_exclusion = 'on';
6103 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0;
6104            QUERY PLAN           
6105 --------------------------------
6106  Aggregate
6107    Output: count(*)
6108    ->  Result
6109          One-Time Filter: false
6110 (4 rows)
6111
6112 SELECT count(*) FROM ft1 WHERE c2 < 0;
6113  count 
6114 -------
6115      0
6116 (1 row)
6117
6118 RESET constraint_exclusion;
6119 -- check constraint is enforced on the remote side, not locally
6120 INSERT INTO ft1(c1, c2) VALUES(1111, -2);  -- c2positive
6121 ERROR:  new row for relation "T 1" violates check constraint "c2positive"
6122 DETAIL:  Failing row contains (1111, -2, null, null, null, null, ft1       , null).
6123 CONTEXT:  Remote SQL command: INSERT INTO "S 1"."T 1"("C 1", c2, c3, c4, c5, c6, c7, c8) VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
6124 UPDATE ft1 SET c2 = -c2 WHERE c1 = 1;  -- c2positive
6125 ERROR:  new row for relation "T 1" violates check constraint "c2positive"
6126 DETAIL:  Failing row contains (1, -1, 00001_trig_update, 1970-01-02 08:00:00+00, 1970-01-02 00:00:00, 1, 1         , foo).
6127 CONTEXT:  Remote SQL command: UPDATE "S 1"."T 1" SET c2 = (- c2) WHERE (("C 1" = 1))
6128 ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive;
6129 -- But inconsistent check constraints provide inconsistent results
6130 ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK (c2 < 0);
6131 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0;
6132                             QUERY PLAN                            
6133 ------------------------------------------------------------------
6134  Foreign Scan
6135    Output: (count(*))
6136    Relations: Aggregate on (public.ft1)
6137    Remote SQL: SELECT count(*) FROM "S 1"."T 1" WHERE ((c2 >= 0))
6138 (4 rows)
6139
6140 SELECT count(*) FROM ft1 WHERE c2 >= 0;
6141  count 
6142 -------
6143    821
6144 (1 row)
6145
6146 SET constraint_exclusion = 'on';
6147 EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0;
6148            QUERY PLAN           
6149 --------------------------------
6150  Aggregate
6151    Output: count(*)
6152    ->  Result
6153          One-Time Filter: false
6154 (4 rows)
6155
6156 SELECT count(*) FROM ft1 WHERE c2 >= 0;
6157  count 
6158 -------
6159      0
6160 (1 row)
6161
6162 RESET constraint_exclusion;
6163 -- local check constraint is not actually enforced
6164 INSERT INTO ft1(c1, c2) VALUES(1111, 2);
6165 UPDATE ft1 SET c2 = c2 + 1 WHERE c1 = 1;
6166 ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2negative;
6167 -- ===================================================================
6168 -- test WITH CHECK OPTION constraints
6169 -- ===================================================================
6170 CREATE TABLE base_tbl (a int, b int);
6171 CREATE FOREIGN TABLE foreign_tbl (a int, b int)
6172   SERVER loopback OPTIONS(table_name 'base_tbl');
6173 CREATE VIEW rw_view AS SELECT * FROM foreign_tbl
6174   WHERE a < b WITH CHECK OPTION;
6175 \d+ rw_view
6176                            View "public.rw_view"
6177  Column |  Type   | Collation | Nullable | Default | Storage | Description 
6178 --------+---------+-----------+----------+---------+---------+-------------
6179  a      | integer |           |          |         | plain   | 
6180  b      | integer |           |          |         | plain   | 
6181 View definition:
6182  SELECT foreign_tbl.a,
6183     foreign_tbl.b
6184    FROM foreign_tbl
6185   WHERE foreign_tbl.a < foreign_tbl.b;
6186 Options: check_option=cascaded
6187
6188 INSERT INTO rw_view VALUES (0, 10); -- ok
6189 INSERT INTO rw_view VALUES (10, 0); -- should fail
6190 ERROR:  new row violates check option for view "rw_view"
6191 DETAIL:  Failing row contains (10, 0).
6192 EXPLAIN (VERBOSE, COSTS OFF)
6193 UPDATE rw_view SET b = 20 WHERE a = 0; -- not pushed down
6194                                             QUERY PLAN                                            
6195 --------------------------------------------------------------------------------------------------
6196  Update on public.foreign_tbl
6197    Remote SQL: UPDATE public.base_tbl SET b = $2 WHERE ctid = $1
6198    ->  Foreign Scan on public.foreign_tbl
6199          Output: foreign_tbl.a, 20, foreign_tbl.ctid
6200          Remote SQL: SELECT a, ctid FROM public.base_tbl WHERE ((a < b)) AND ((a = 0)) FOR UPDATE
6201 (5 rows)
6202
6203 UPDATE rw_view SET b = 20 WHERE a = 0; -- ok
6204 EXPLAIN (VERBOSE, COSTS OFF)
6205 UPDATE rw_view SET b = -20 WHERE a = 0; -- not pushed down
6206                                             QUERY PLAN                                            
6207 --------------------------------------------------------------------------------------------------
6208  Update on public.foreign_tbl
6209    Remote SQL: UPDATE public.base_tbl SET b = $2 WHERE ctid = $1
6210    ->  Foreign Scan on public.foreign_tbl
6211          Output: foreign_tbl.a, '-20'::integer, foreign_tbl.ctid
6212          Remote SQL: SELECT a, ctid FROM public.base_tbl WHERE ((a < b)) AND ((a = 0)) FOR UPDATE
6213 (5 rows)
6214
6215 UPDATE rw_view SET b = -20 WHERE a = 0; -- should fail
6216 ERROR:  new row violates check option for view "rw_view"
6217 DETAIL:  Failing row contains (0, -20).
6218 SELECT * FROM foreign_tbl;
6219  a | b  
6220 ---+----
6221  0 | 20
6222 (1 row)
6223
6224 DROP FOREIGN TABLE foreign_tbl CASCADE;
6225 NOTICE:  drop cascades to view rw_view
6226 DROP TABLE base_tbl;
6227 -- ===================================================================
6228 -- test serial columns (ie, sequence-based defaults)
6229 -- ===================================================================
6230 create table loc1 (f1 serial, f2 text);
6231 create foreign table rem1 (f1 serial, f2 text)
6232   server loopback options(table_name 'loc1');
6233 select pg_catalog.setval('rem1_f1_seq', 10, false);
6234  setval 
6235 --------
6236      10
6237 (1 row)
6238
6239 insert into loc1(f2) values('hi');
6240 insert into rem1(f2) values('hi remote');
6241 insert into loc1(f2) values('bye');
6242 insert into rem1(f2) values('bye remote');
6243 select * from loc1;
6244  f1 |     f2     
6245 ----+------------
6246   1 | hi
6247  10 | hi remote
6248   2 | bye
6249  11 | bye remote
6250 (4 rows)
6251
6252 select * from rem1;
6253  f1 |     f2     
6254 ----+------------
6255   1 | hi
6256  10 | hi remote
6257   2 | bye
6258  11 | bye remote
6259 (4 rows)
6260
6261 -- ===================================================================
6262 -- test local triggers
6263 -- ===================================================================
6264 -- Trigger functions "borrowed" from triggers regress test.
6265 CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$
6266 BEGIN
6267         RAISE NOTICE 'trigger_func(%) called: action = %, when = %, level = %',
6268                 TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL;
6269         RETURN NULL;
6270 END;$$;
6271 CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE ON rem1
6272         FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
6273 CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE ON rem1
6274         FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
6275 CREATE OR REPLACE FUNCTION trigger_data()  RETURNS trigger
6276 LANGUAGE plpgsql AS $$
6277
6278 declare
6279         oldnew text[];
6280         relid text;
6281     argstr text;
6282 begin
6283
6284         relid := TG_relid::regclass;
6285         argstr := '';
6286         for i in 0 .. TG_nargs - 1 loop
6287                 if i > 0 then
6288                         argstr := argstr || ', ';
6289                 end if;
6290                 argstr := argstr || TG_argv[i];
6291         end loop;
6292
6293     RAISE NOTICE '%(%) % % % ON %',
6294                 tg_name, argstr, TG_when, TG_level, TG_OP, relid;
6295     oldnew := '{}'::text[];
6296         if TG_OP != 'INSERT' then
6297                 oldnew := array_append(oldnew, format('OLD: %s', OLD));
6298         end if;
6299
6300         if TG_OP != 'DELETE' then
6301                 oldnew := array_append(oldnew, format('NEW: %s', NEW));
6302         end if;
6303
6304     RAISE NOTICE '%', array_to_string(oldnew, ',');
6305
6306         if TG_OP = 'DELETE' then
6307                 return OLD;
6308         else
6309                 return NEW;
6310         end if;
6311 end;
6312 $$;
6313 -- Test basic functionality
6314 CREATE TRIGGER trig_row_before
6315 BEFORE INSERT OR UPDATE OR DELETE ON rem1
6316 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
6317 CREATE TRIGGER trig_row_after
6318 AFTER INSERT OR UPDATE OR DELETE ON rem1
6319 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
6320 delete from rem1;
6321 NOTICE:  trigger_func(<NULL>) called: action = DELETE, when = BEFORE, level = STATEMENT
6322 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
6323 NOTICE:  OLD: (1,hi)
6324 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
6325 NOTICE:  OLD: (10,"hi remote")
6326 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
6327 NOTICE:  OLD: (2,bye)
6328 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
6329 NOTICE:  OLD: (11,"bye remote")
6330 NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
6331 NOTICE:  OLD: (1,hi)
6332 NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
6333 NOTICE:  OLD: (10,"hi remote")
6334 NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
6335 NOTICE:  OLD: (2,bye)
6336 NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
6337 NOTICE:  OLD: (11,"bye remote")
6338 NOTICE:  trigger_func(<NULL>) called: action = DELETE, when = AFTER, level = STATEMENT
6339 insert into rem1 values(1,'insert');
6340 NOTICE:  trigger_func(<NULL>) called: action = INSERT, when = BEFORE, level = STATEMENT
6341 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
6342 NOTICE:  NEW: (1,insert)
6343 NOTICE:  trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
6344 NOTICE:  NEW: (1,insert)
6345 NOTICE:  trigger_func(<NULL>) called: action = INSERT, when = AFTER, level = STATEMENT
6346 update rem1 set f2  = 'update' where f1 = 1;
6347 NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = BEFORE, level = STATEMENT
6348 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
6349 NOTICE:  OLD: (1,insert),NEW: (1,update)
6350 NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
6351 NOTICE:  OLD: (1,insert),NEW: (1,update)
6352 NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
6353 update rem1 set f2 = f2 || f2;
6354 NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = BEFORE, level = STATEMENT
6355 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
6356 NOTICE:  OLD: (1,update),NEW: (1,updateupdate)
6357 NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
6358 NOTICE:  OLD: (1,update),NEW: (1,updateupdate)
6359 NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
6360 -- cleanup
6361 DROP TRIGGER trig_row_before ON rem1;
6362 DROP TRIGGER trig_row_after ON rem1;
6363 DROP TRIGGER trig_stmt_before ON rem1;
6364 DROP TRIGGER trig_stmt_after ON rem1;
6365 DELETE from rem1;
6366 -- Test WHEN conditions
6367 CREATE TRIGGER trig_row_before_insupd
6368 BEFORE INSERT OR UPDATE ON rem1
6369 FOR EACH ROW
6370 WHEN (NEW.f2 like '%update%')
6371 EXECUTE PROCEDURE trigger_data(23,'skidoo');
6372 CREATE TRIGGER trig_row_after_insupd
6373 AFTER INSERT OR UPDATE ON rem1
6374 FOR EACH ROW
6375 WHEN (NEW.f2 like '%update%')
6376 EXECUTE PROCEDURE trigger_data(23,'skidoo');
6377 -- Insert or update not matching: nothing happens
6378 INSERT INTO rem1 values(1, 'insert');
6379 UPDATE rem1 set f2 = 'test';
6380 -- Insert or update matching: triggers are fired
6381 INSERT INTO rem1 values(2, 'update');
6382 NOTICE:  trig_row_before_insupd(23, skidoo) BEFORE ROW INSERT ON rem1
6383 NOTICE:  NEW: (2,update)
6384 NOTICE:  trig_row_after_insupd(23, skidoo) AFTER ROW INSERT ON rem1
6385 NOTICE:  NEW: (2,update)
6386 UPDATE rem1 set f2 = 'update update' where f1 = '2';
6387 NOTICE:  trig_row_before_insupd(23, skidoo) BEFORE ROW UPDATE ON rem1
6388 NOTICE:  OLD: (2,update),NEW: (2,"update update")
6389 NOTICE:  trig_row_after_insupd(23, skidoo) AFTER ROW UPDATE ON rem1
6390 NOTICE:  OLD: (2,update),NEW: (2,"update update")
6391 CREATE TRIGGER trig_row_before_delete
6392 BEFORE DELETE ON rem1
6393 FOR EACH ROW
6394 WHEN (OLD.f2 like '%update%')
6395 EXECUTE PROCEDURE trigger_data(23,'skidoo');
6396 CREATE TRIGGER trig_row_after_delete
6397 AFTER DELETE ON rem1
6398 FOR EACH ROW
6399 WHEN (OLD.f2 like '%update%')
6400 EXECUTE PROCEDURE trigger_data(23,'skidoo');
6401 -- Trigger is fired for f1=2, not for f1=1
6402 DELETE FROM rem1;
6403 NOTICE:  trig_row_before_delete(23, skidoo) BEFORE ROW DELETE ON rem1
6404 NOTICE:  OLD: (2,"update update")
6405 NOTICE:  trig_row_after_delete(23, skidoo) AFTER ROW DELETE ON rem1
6406 NOTICE:  OLD: (2,"update update")
6407 -- cleanup
6408 DROP TRIGGER trig_row_before_insupd ON rem1;
6409 DROP TRIGGER trig_row_after_insupd ON rem1;
6410 DROP TRIGGER trig_row_before_delete ON rem1;
6411 DROP TRIGGER trig_row_after_delete ON rem1;
6412 -- Test various RETURN statements in BEFORE triggers.
6413 CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$
6414   BEGIN
6415     NEW.f2 := NEW.f2 || ' triggered !';
6416     RETURN NEW;
6417   END
6418 $$ language plpgsql;
6419 CREATE TRIGGER trig_row_before_insupd
6420 BEFORE INSERT OR UPDATE ON rem1
6421 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
6422 -- The new values should have 'triggered' appended
6423 INSERT INTO rem1 values(1, 'insert');
6424 SELECT * from loc1;
6425  f1 |         f2         
6426 ----+--------------------
6427   1 | insert triggered !
6428 (1 row)
6429
6430 INSERT INTO rem1 values(2, 'insert') RETURNING f2;
6431          f2         
6432 --------------------
6433  insert triggered !
6434 (1 row)
6435
6436 SELECT * from loc1;
6437  f1 |         f2         
6438 ----+--------------------
6439   1 | insert triggered !
6440   2 | insert triggered !
6441 (2 rows)
6442
6443 UPDATE rem1 set f2 = '';
6444 SELECT * from loc1;
6445  f1 |      f2      
6446 ----+--------------
6447   1 |  triggered !
6448   2 |  triggered !
6449 (2 rows)
6450
6451 UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
6452          f2         
6453 --------------------
6454  skidoo triggered !
6455  skidoo triggered !
6456 (2 rows)
6457
6458 SELECT * from loc1;
6459  f1 |         f2         
6460 ----+--------------------
6461   1 | skidoo triggered !
6462   2 | skidoo triggered !
6463 (2 rows)
6464
6465 DELETE FROM rem1;
6466 -- Add a second trigger, to check that the changes are propagated correctly
6467 -- from trigger to trigger
6468 CREATE TRIGGER trig_row_before_insupd2
6469 BEFORE INSERT OR UPDATE ON rem1
6470 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
6471 INSERT INTO rem1 values(1, 'insert');
6472 SELECT * from loc1;
6473  f1 |               f2               
6474 ----+--------------------------------
6475   1 | insert triggered ! triggered !
6476 (1 row)
6477
6478 INSERT INTO rem1 values(2, 'insert') RETURNING f2;
6479                f2               
6480 --------------------------------
6481  insert triggered ! triggered !
6482 (1 row)
6483
6484 SELECT * from loc1;
6485  f1 |               f2               
6486 ----+--------------------------------
6487   1 | insert triggered ! triggered !
6488   2 | insert triggered ! triggered !
6489 (2 rows)
6490
6491 UPDATE rem1 set f2 = '';
6492 SELECT * from loc1;
6493  f1 |            f2            
6494 ----+--------------------------
6495   1 |  triggered ! triggered !
6496   2 |  triggered ! triggered !
6497 (2 rows)
6498
6499 UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
6500                f2               
6501 --------------------------------
6502  skidoo triggered ! triggered !
6503  skidoo triggered ! triggered !
6504 (2 rows)
6505
6506 SELECT * from loc1;
6507  f1 |               f2               
6508 ----+--------------------------------
6509   1 | skidoo triggered ! triggered !
6510   2 | skidoo triggered ! triggered !
6511 (2 rows)
6512
6513 DROP TRIGGER trig_row_before_insupd ON rem1;
6514 DROP TRIGGER trig_row_before_insupd2 ON rem1;
6515 DELETE from rem1;
6516 INSERT INTO rem1 VALUES (1, 'test');
6517 -- Test with a trigger returning NULL
6518 CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$
6519   BEGIN
6520     RETURN NULL;
6521   END
6522 $$ language plpgsql;
6523 CREATE TRIGGER trig_null
6524 BEFORE INSERT OR UPDATE OR DELETE ON rem1
6525 FOR EACH ROW EXECUTE PROCEDURE trig_null();
6526 -- Nothing should have changed.
6527 INSERT INTO rem1 VALUES (2, 'test2');
6528 SELECT * from loc1;
6529  f1 |  f2  
6530 ----+------
6531   1 | test
6532 (1 row)
6533
6534 UPDATE rem1 SET f2 = 'test2';
6535 SELECT * from loc1;
6536  f1 |  f2  
6537 ----+------
6538   1 | test
6539 (1 row)
6540
6541 DELETE from rem1;
6542 SELECT * from loc1;
6543  f1 |  f2  
6544 ----+------
6545   1 | test
6546 (1 row)
6547
6548 DROP TRIGGER trig_null ON rem1;
6549 DELETE from rem1;
6550 -- Test a combination of local and remote triggers
6551 CREATE TRIGGER trig_row_before
6552 BEFORE INSERT OR UPDATE OR DELETE ON rem1
6553 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
6554 CREATE TRIGGER trig_row_after
6555 AFTER INSERT OR UPDATE OR DELETE ON rem1
6556 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
6557 CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON loc1
6558 FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
6559 INSERT INTO rem1(f2) VALUES ('test');
6560 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
6561 NOTICE:  NEW: (12,test)
6562 NOTICE:  trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
6563 NOTICE:  NEW: (12,"test triggered !")
6564 UPDATE rem1 SET f2 = 'testo';
6565 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
6566 NOTICE:  OLD: (12,"test triggered !"),NEW: (12,testo)
6567 NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
6568 NOTICE:  OLD: (12,"test triggered !"),NEW: (12,"testo triggered !")
6569 -- Test returning a system attribute
6570 INSERT INTO rem1(f2) VALUES ('test') RETURNING ctid;
6571 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
6572 NOTICE:  NEW: (13,test)
6573 NOTICE:  trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
6574 NOTICE:  NEW: (13,"test triggered !")
6575   ctid  
6576 --------
6577  (0,27)
6578 (1 row)
6579
6580 -- cleanup
6581 DROP TRIGGER trig_row_before ON rem1;
6582 DROP TRIGGER trig_row_after ON rem1;
6583 DROP TRIGGER trig_local_before ON loc1;
6584 -- Test direct foreign table modification functionality
6585 -- Test with statement-level triggers
6586 CREATE TRIGGER trig_stmt_before
6587         BEFORE DELETE OR INSERT OR UPDATE ON rem1
6588         FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
6589 EXPLAIN (verbose, costs off)
6590 UPDATE rem1 set f2 = '';          -- can be pushed down
6591                         QUERY PLAN                        
6592 ----------------------------------------------------------
6593  Update on public.rem1
6594    ->  Foreign Update on public.rem1
6595          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
6596 (3 rows)
6597
6598 EXPLAIN (verbose, costs off)
6599 DELETE FROM rem1;                 -- can be pushed down
6600                  QUERY PLAN                  
6601 ---------------------------------------------
6602  Delete on public.rem1
6603    ->  Foreign Delete on public.rem1
6604          Remote SQL: DELETE FROM public.loc1
6605 (3 rows)
6606
6607 DROP TRIGGER trig_stmt_before ON rem1;
6608 CREATE TRIGGER trig_stmt_after
6609         AFTER DELETE OR INSERT OR UPDATE ON rem1
6610         FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
6611 EXPLAIN (verbose, costs off)
6612 UPDATE rem1 set f2 = '';          -- can be pushed down
6613                         QUERY PLAN                        
6614 ----------------------------------------------------------
6615  Update on public.rem1
6616    ->  Foreign Update on public.rem1
6617          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
6618 (3 rows)
6619
6620 EXPLAIN (verbose, costs off)
6621 DELETE FROM rem1;                 -- can be pushed down
6622                  QUERY PLAN                  
6623 ---------------------------------------------
6624  Delete on public.rem1
6625    ->  Foreign Delete on public.rem1
6626          Remote SQL: DELETE FROM public.loc1
6627 (3 rows)
6628
6629 DROP TRIGGER trig_stmt_after ON rem1;
6630 -- Test with row-level ON INSERT triggers
6631 CREATE TRIGGER trig_row_before_insert
6632 BEFORE INSERT ON rem1
6633 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
6634 EXPLAIN (verbose, costs off)
6635 UPDATE rem1 set f2 = '';          -- can be pushed down
6636                         QUERY PLAN                        
6637 ----------------------------------------------------------
6638  Update on public.rem1
6639    ->  Foreign Update on public.rem1
6640          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
6641 (3 rows)
6642
6643 EXPLAIN (verbose, costs off)
6644 DELETE FROM rem1;                 -- can be pushed down
6645                  QUERY PLAN                  
6646 ---------------------------------------------
6647  Delete on public.rem1
6648    ->  Foreign Delete on public.rem1
6649          Remote SQL: DELETE FROM public.loc1
6650 (3 rows)
6651
6652 DROP TRIGGER trig_row_before_insert ON rem1;
6653 CREATE TRIGGER trig_row_after_insert
6654 AFTER INSERT ON rem1
6655 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
6656 EXPLAIN (verbose, costs off)
6657 UPDATE rem1 set f2 = '';          -- can be pushed down
6658                         QUERY PLAN                        
6659 ----------------------------------------------------------
6660  Update on public.rem1
6661    ->  Foreign Update on public.rem1
6662          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
6663 (3 rows)
6664
6665 EXPLAIN (verbose, costs off)
6666 DELETE FROM rem1;                 -- can be pushed down
6667                  QUERY PLAN                  
6668 ---------------------------------------------
6669  Delete on public.rem1
6670    ->  Foreign Delete on public.rem1
6671          Remote SQL: DELETE FROM public.loc1
6672 (3 rows)
6673
6674 DROP TRIGGER trig_row_after_insert ON rem1;
6675 -- Test with row-level ON UPDATE triggers
6676 CREATE TRIGGER trig_row_before_update
6677 BEFORE UPDATE ON rem1
6678 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
6679 EXPLAIN (verbose, costs off)
6680 UPDATE rem1 set f2 = '';          -- can't be pushed down
6681                              QUERY PLAN                              
6682 ---------------------------------------------------------------------
6683  Update on public.rem1
6684    Remote SQL: UPDATE public.loc1 SET f2 = $2 WHERE ctid = $1
6685    ->  Foreign Scan on public.rem1
6686          Output: f1, ''::text, ctid, rem1.*
6687          Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
6688 (5 rows)
6689
6690 EXPLAIN (verbose, costs off)
6691 DELETE FROM rem1;                 -- can be pushed down
6692                  QUERY PLAN                  
6693 ---------------------------------------------
6694  Delete on public.rem1
6695    ->  Foreign Delete on public.rem1
6696          Remote SQL: DELETE FROM public.loc1
6697 (3 rows)
6698
6699 DROP TRIGGER trig_row_before_update ON rem1;
6700 CREATE TRIGGER trig_row_after_update
6701 AFTER UPDATE ON rem1
6702 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
6703 EXPLAIN (verbose, costs off)
6704 UPDATE rem1 set f2 = '';          -- can't be pushed down
6705                                   QUERY PLAN                                   
6706 -------------------------------------------------------------------------------
6707  Update on public.rem1
6708    Remote SQL: UPDATE public.loc1 SET f2 = $2 WHERE ctid = $1 RETURNING f1, f2
6709    ->  Foreign Scan on public.rem1
6710          Output: f1, ''::text, ctid, rem1.*
6711          Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
6712 (5 rows)
6713
6714 EXPLAIN (verbose, costs off)
6715 DELETE FROM rem1;                 -- can be pushed down
6716                  QUERY PLAN                  
6717 ---------------------------------------------
6718  Delete on public.rem1
6719    ->  Foreign Delete on public.rem1
6720          Remote SQL: DELETE FROM public.loc1
6721 (3 rows)
6722
6723 DROP TRIGGER trig_row_after_update ON rem1;
6724 -- Test with row-level ON DELETE triggers
6725 CREATE TRIGGER trig_row_before_delete
6726 BEFORE DELETE ON rem1
6727 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
6728 EXPLAIN (verbose, costs off)
6729 UPDATE rem1 set f2 = '';          -- can be pushed down
6730                         QUERY PLAN                        
6731 ----------------------------------------------------------
6732  Update on public.rem1
6733    ->  Foreign Update on public.rem1
6734          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
6735 (3 rows)
6736
6737 EXPLAIN (verbose, costs off)
6738 DELETE FROM rem1;                 -- can't be pushed down
6739                              QUERY PLAN                              
6740 ---------------------------------------------------------------------
6741  Delete on public.rem1
6742    Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1
6743    ->  Foreign Scan on public.rem1
6744          Output: ctid, rem1.*
6745          Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
6746 (5 rows)
6747
6748 DROP TRIGGER trig_row_before_delete ON rem1;
6749 CREATE TRIGGER trig_row_after_delete
6750 AFTER DELETE ON rem1
6751 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
6752 EXPLAIN (verbose, costs off)
6753 UPDATE rem1 set f2 = '';          -- can be pushed down
6754                         QUERY PLAN                        
6755 ----------------------------------------------------------
6756  Update on public.rem1
6757    ->  Foreign Update on public.rem1
6758          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
6759 (3 rows)
6760
6761 EXPLAIN (verbose, costs off)
6762 DELETE FROM rem1;                 -- can't be pushed down
6763                                QUERY PLAN                               
6764 ------------------------------------------------------------------------
6765  Delete on public.rem1
6766    Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1 RETURNING f1, f2
6767    ->  Foreign Scan on public.rem1
6768          Output: ctid, rem1.*
6769          Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
6770 (5 rows)
6771
6772 DROP TRIGGER trig_row_after_delete ON rem1;
6773 -- ===================================================================
6774 -- test inheritance features
6775 -- ===================================================================
6776 CREATE TABLE a (aa TEXT);
6777 CREATE TABLE loct (aa TEXT, bb TEXT);
6778 CREATE FOREIGN TABLE b (bb TEXT) INHERITS (a)
6779   SERVER loopback OPTIONS (table_name 'loct');
6780 INSERT INTO a(aa) VALUES('aaa');
6781 INSERT INTO a(aa) VALUES('aaaa');
6782 INSERT INTO a(aa) VALUES('aaaaa');
6783 INSERT INTO b(aa) VALUES('bbb');
6784 INSERT INTO b(aa) VALUES('bbbb');
6785 INSERT INTO b(aa) VALUES('bbbbb');
6786 SELECT tableoid::regclass, * FROM a;
6787  tableoid |  aa   
6788 ----------+-------
6789  a        | aaa
6790  a        | aaaa
6791  a        | aaaaa
6792  b        | bbb
6793  b        | bbbb
6794  b        | bbbbb
6795 (6 rows)
6796
6797 SELECT tableoid::regclass, * FROM b;
6798  tableoid |  aa   | bb 
6799 ----------+-------+----
6800  b        | bbb   | 
6801  b        | bbbb  | 
6802  b        | bbbbb | 
6803 (3 rows)
6804
6805 SELECT tableoid::regclass, * FROM ONLY a;
6806  tableoid |  aa   
6807 ----------+-------
6808  a        | aaa
6809  a        | aaaa
6810  a        | aaaaa
6811 (3 rows)
6812
6813 UPDATE a SET aa = 'zzzzzz' WHERE aa LIKE 'aaaa%';
6814 SELECT tableoid::regclass, * FROM a;
6815  tableoid |   aa   
6816 ----------+--------
6817  a        | aaa
6818  a        | zzzzzz
6819  a        | zzzzzz
6820  b        | bbb
6821  b        | bbbb
6822  b        | bbbbb
6823 (6 rows)
6824
6825 SELECT tableoid::regclass, * FROM b;
6826  tableoid |  aa   | bb 
6827 ----------+-------+----
6828  b        | bbb   | 
6829  b        | bbbb  | 
6830  b        | bbbbb | 
6831 (3 rows)
6832
6833 SELECT tableoid::regclass, * FROM ONLY a;
6834  tableoid |   aa   
6835 ----------+--------
6836  a        | aaa
6837  a        | zzzzzz
6838  a        | zzzzzz
6839 (3 rows)
6840
6841 UPDATE b SET aa = 'new';
6842 SELECT tableoid::regclass, * FROM a;
6843  tableoid |   aa   
6844 ----------+--------
6845  a        | aaa
6846  a        | zzzzzz
6847  a        | zzzzzz
6848  b        | new
6849  b        | new
6850  b        | new
6851 (6 rows)
6852
6853 SELECT tableoid::regclass, * FROM b;
6854  tableoid | aa  | bb 
6855 ----------+-----+----
6856  b        | new | 
6857  b        | new | 
6858  b        | new | 
6859 (3 rows)
6860
6861 SELECT tableoid::regclass, * FROM ONLY a;
6862  tableoid |   aa   
6863 ----------+--------
6864  a        | aaa
6865  a        | zzzzzz
6866  a        | zzzzzz
6867 (3 rows)
6868
6869 UPDATE a SET aa = 'newtoo';
6870 SELECT tableoid::regclass, * FROM a;
6871  tableoid |   aa   
6872 ----------+--------
6873  a        | newtoo
6874  a        | newtoo
6875  a        | newtoo
6876  b        | newtoo
6877  b        | newtoo
6878  b        | newtoo
6879 (6 rows)
6880
6881 SELECT tableoid::regclass, * FROM b;
6882  tableoid |   aa   | bb 
6883 ----------+--------+----
6884  b        | newtoo | 
6885  b        | newtoo | 
6886  b        | newtoo | 
6887 (3 rows)
6888
6889 SELECT tableoid::regclass, * FROM ONLY a;
6890  tableoid |   aa   
6891 ----------+--------
6892  a        | newtoo
6893  a        | newtoo
6894  a        | newtoo
6895 (3 rows)
6896
6897 DELETE FROM a;
6898 SELECT tableoid::regclass, * FROM a;
6899  tableoid | aa 
6900 ----------+----
6901 (0 rows)
6902
6903 SELECT tableoid::regclass, * FROM b;
6904  tableoid | aa | bb 
6905 ----------+----+----
6906 (0 rows)
6907
6908 SELECT tableoid::regclass, * FROM ONLY a;
6909  tableoid | aa 
6910 ----------+----
6911 (0 rows)
6912
6913 DROP TABLE a CASCADE;
6914 NOTICE:  drop cascades to foreign table b
6915 DROP TABLE loct;
6916 -- Check SELECT FOR UPDATE/SHARE with an inherited source table
6917 create table loct1 (f1 int, f2 int, f3 int);
6918 create table loct2 (f1 int, f2 int, f3 int);
6919 create table foo (f1 int, f2 int);
6920 create foreign table foo2 (f3 int) inherits (foo)
6921   server loopback options (table_name 'loct1');
6922 create table bar (f1 int, f2 int);
6923 create foreign table bar2 (f3 int) inherits (bar)
6924   server loopback options (table_name 'loct2');
6925 insert into foo values(1,1);
6926 insert into foo values(3,3);
6927 insert into foo2 values(2,2,2);
6928 insert into foo2 values(4,4,4);
6929 insert into bar values(1,11);
6930 insert into bar values(2,22);
6931 insert into bar values(6,66);
6932 insert into bar2 values(3,33,33);
6933 insert into bar2 values(4,44,44);
6934 insert into bar2 values(7,77,77);
6935 explain (verbose, costs off)
6936 select * from bar where f1 in (select f1 from foo) for update;
6937                                           QUERY PLAN                                          
6938 ----------------------------------------------------------------------------------------------
6939  LockRows
6940    Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
6941    ->  Hash Join
6942          Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
6943          Inner Unique: true
6944          Hash Cond: (bar.f1 = foo.f1)
6945          ->  Append
6946                ->  Seq Scan on public.bar
6947                      Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid
6948                ->  Foreign Scan on public.bar2
6949                      Output: bar2.f1, bar2.f2, bar2.ctid, bar2.*, bar2.tableoid
6950                      Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
6951          ->  Hash
6952                Output: foo.ctid, foo.*, foo.tableoid, foo.f1
6953                ->  HashAggregate
6954                      Output: foo.ctid, foo.*, foo.tableoid, foo.f1
6955                      Group Key: foo.f1
6956                      ->  Append
6957                            ->  Seq Scan on public.foo
6958                                  Output: foo.ctid, foo.*, foo.tableoid, foo.f1
6959                            ->  Foreign Scan on public.foo2
6960                                  Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
6961                                  Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
6962 (23 rows)
6963
6964 select * from bar where f1 in (select f1 from foo) for update;
6965  f1 | f2 
6966 ----+----
6967   1 | 11
6968   2 | 22
6969   3 | 33
6970   4 | 44
6971 (4 rows)
6972
6973 explain (verbose, costs off)
6974 select * from bar where f1 in (select f1 from foo) for share;
6975                                           QUERY PLAN                                          
6976 ----------------------------------------------------------------------------------------------
6977  LockRows
6978    Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
6979    ->  Hash Join
6980          Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
6981          Inner Unique: true
6982          Hash Cond: (bar.f1 = foo.f1)
6983          ->  Append
6984                ->  Seq Scan on public.bar
6985                      Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid
6986                ->  Foreign Scan on public.bar2
6987                      Output: bar2.f1, bar2.f2, bar2.ctid, bar2.*, bar2.tableoid
6988                      Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
6989          ->  Hash
6990                Output: foo.ctid, foo.*, foo.tableoid, foo.f1
6991                ->  HashAggregate
6992                      Output: foo.ctid, foo.*, foo.tableoid, foo.f1
6993                      Group Key: foo.f1
6994                      ->  Append
6995                            ->  Seq Scan on public.foo
6996                                  Output: foo.ctid, foo.*, foo.tableoid, foo.f1
6997                            ->  Foreign Scan on public.foo2
6998                                  Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
6999                                  Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
7000 (23 rows)
7001
7002 select * from bar where f1 in (select f1 from foo) for share;
7003  f1 | f2 
7004 ----+----
7005   1 | 11
7006   2 | 22
7007   3 | 33
7008   4 | 44
7009 (4 rows)
7010
7011 -- Check UPDATE with inherited target and an inherited source table
7012 explain (verbose, costs off)
7013 update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
7014                                          QUERY PLAN                                          
7015 ---------------------------------------------------------------------------------------------
7016  Update on public.bar
7017    Update on public.bar
7018    Foreign Update on public.bar2
7019      Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
7020    ->  Hash Join
7021          Output: bar.f1, (bar.f2 + 100), bar.ctid, foo.ctid, foo.*, foo.tableoid
7022          Inner Unique: true
7023          Hash Cond: (bar.f1 = foo.f1)
7024          ->  Seq Scan on public.bar
7025                Output: bar.f1, bar.f2, bar.ctid
7026          ->  Hash
7027                Output: foo.ctid, foo.*, foo.tableoid, foo.f1
7028                ->  HashAggregate
7029                      Output: foo.ctid, foo.*, foo.tableoid, foo.f1
7030                      Group Key: foo.f1
7031                      ->  Append
7032                            ->  Seq Scan on public.foo
7033                                  Output: foo.ctid, foo.*, foo.tableoid, foo.f1
7034                            ->  Foreign Scan on public.foo2
7035                                  Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
7036                                  Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
7037    ->  Hash Join
7038          Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.ctid, foo.ctid, foo.*, foo.tableoid
7039          Inner Unique: true
7040          Hash Cond: (bar2.f1 = foo.f1)
7041          ->  Foreign Scan on public.bar2
7042                Output: bar2.f1, bar2.f2, bar2.f3, bar2.ctid
7043                Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
7044          ->  Hash
7045                Output: foo.ctid, foo.*, foo.tableoid, foo.f1
7046                ->  HashAggregate
7047                      Output: foo.ctid, foo.*, foo.tableoid, foo.f1
7048                      Group Key: foo.f1
7049                      ->  Append
7050                            ->  Seq Scan on public.foo
7051                                  Output: foo.ctid, foo.*, foo.tableoid, foo.f1
7052                            ->  Foreign Scan on public.foo2
7053                                  Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
7054                                  Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
7055 (39 rows)
7056
7057 update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
7058 select tableoid::regclass, * from bar order by 1,2;
7059  tableoid | f1 | f2  
7060 ----------+----+-----
7061  bar      |  1 | 111
7062  bar      |  2 | 122
7063  bar      |  6 |  66
7064  bar2     |  3 | 133
7065  bar2     |  4 | 144
7066  bar2     |  7 |  77
7067 (6 rows)
7068
7069 -- Check UPDATE with inherited target and an appendrel subquery
7070 explain (verbose, costs off)
7071 update bar set f2 = f2 + 100
7072 from
7073   ( select f1 from foo union all select f1+3 from foo ) ss
7074 where bar.f1 = ss.f1;
7075                                       QUERY PLAN                                      
7076 --------------------------------------------------------------------------------------
7077  Update on public.bar
7078    Update on public.bar
7079    Foreign Update on public.bar2
7080      Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
7081    ->  Hash Join
7082          Output: bar.f1, (bar.f2 + 100), bar.ctid, (ROW(foo.f1))
7083          Hash Cond: (foo.f1 = bar.f1)
7084          ->  Append
7085                ->  Seq Scan on public.foo
7086                      Output: ROW(foo.f1), foo.f1
7087                ->  Foreign Scan on public.foo2
7088                      Output: ROW(foo2.f1), foo2.f1
7089                      Remote SQL: SELECT f1 FROM public.loct1
7090                ->  Seq Scan on public.foo foo_1
7091                      Output: ROW((foo_1.f1 + 3)), (foo_1.f1 + 3)
7092                ->  Foreign Scan on public.foo2 foo2_1
7093                      Output: ROW((foo2_1.f1 + 3)), (foo2_1.f1 + 3)
7094                      Remote SQL: SELECT f1 FROM public.loct1
7095          ->  Hash
7096                Output: bar.f1, bar.f2, bar.ctid
7097                ->  Seq Scan on public.bar
7098                      Output: bar.f1, bar.f2, bar.ctid
7099    ->  Merge Join
7100          Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.ctid, (ROW(foo.f1))
7101          Merge Cond: (bar2.f1 = foo.f1)
7102          ->  Sort
7103                Output: bar2.f1, bar2.f2, bar2.f3, bar2.ctid
7104                Sort Key: bar2.f1
7105                ->  Foreign Scan on public.bar2
7106                      Output: bar2.f1, bar2.f2, bar2.f3, bar2.ctid
7107                      Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
7108          ->  Sort
7109                Output: (ROW(foo.f1)), foo.f1
7110                Sort Key: foo.f1
7111                ->  Append
7112                      ->  Seq Scan on public.foo
7113                            Output: ROW(foo.f1), foo.f1
7114                      ->  Foreign Scan on public.foo2
7115                            Output: ROW(foo2.f1), foo2.f1
7116                            Remote SQL: SELECT f1 FROM public.loct1
7117                      ->  Seq Scan on public.foo foo_1
7118                            Output: ROW((foo_1.f1 + 3)), (foo_1.f1 + 3)
7119                      ->  Foreign Scan on public.foo2 foo2_1
7120                            Output: ROW((foo2_1.f1 + 3)), (foo2_1.f1 + 3)
7121                            Remote SQL: SELECT f1 FROM public.loct1
7122 (45 rows)
7123
7124 update bar set f2 = f2 + 100
7125 from
7126   ( select f1 from foo union all select f1+3 from foo ) ss
7127 where bar.f1 = ss.f1;
7128 select tableoid::regclass, * from bar order by 1,2;
7129  tableoid | f1 | f2  
7130 ----------+----+-----
7131  bar      |  1 | 211
7132  bar      |  2 | 222
7133  bar      |  6 | 166
7134  bar2     |  3 | 233
7135  bar2     |  4 | 244
7136  bar2     |  7 | 177
7137 (6 rows)
7138
7139 -- Test forcing the remote server to produce sorted data for a merge join,
7140 -- but the foreign table is an inheritance child.
7141 truncate table loct1;
7142 truncate table only foo;
7143 \set num_rows_foo 2000
7144 insert into loct1 select generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2), generate_series(0, :num_rows_foo, 2);
7145 insert into foo select generate_series(1, :num_rows_foo, 2), generate_series(1, :num_rows_foo, 2);
7146 SET enable_hashjoin to false;
7147 SET enable_nestloop to false;
7148 alter foreign table foo2 options (use_remote_estimate 'true');
7149 create index i_loct1_f1 on loct1(f1);
7150 create index i_foo_f1 on foo(f1);
7151 analyze foo;
7152 analyze loct1;
7153 -- inner join; expressions in the clauses appear in the equivalence class list
7154 explain (verbose, costs off)
7155         select foo.f1, loct1.f1 from foo join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
7156                                             QUERY PLAN                                            
7157 --------------------------------------------------------------------------------------------------
7158  Limit
7159    Output: foo.f1, loct1.f1, foo.f2
7160    ->  Sort
7161          Output: foo.f1, loct1.f1, foo.f2
7162          Sort Key: foo.f2
7163          ->  Merge Join
7164                Output: foo.f1, loct1.f1, foo.f2
7165                Merge Cond: (foo.f1 = loct1.f1)
7166                ->  Merge Append
7167                      Sort Key: foo.f1
7168                      ->  Index Scan using i_foo_f1 on public.foo
7169                            Output: foo.f1, foo.f2
7170                      ->  Foreign Scan on public.foo2
7171                            Output: foo2.f1, foo2.f2
7172                            Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
7173                ->  Index Only Scan using i_loct1_f1 on public.loct1
7174                      Output: loct1.f1
7175 (17 rows)
7176
7177 select foo.f1, loct1.f1 from foo join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
7178  f1 | f1 
7179 ----+----
7180  20 | 20
7181  22 | 22
7182  24 | 24
7183  26 | 26
7184  28 | 28
7185  30 | 30
7186  32 | 32
7187  34 | 34
7188  36 | 36
7189  38 | 38
7190 (10 rows)
7191
7192 -- outer join; expressions in the clauses do not appear in equivalence class
7193 -- list but no output change as compared to the previous query
7194 explain (verbose, costs off)
7195         select foo.f1, loct1.f1 from foo left join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
7196                                             QUERY PLAN                                            
7197 --------------------------------------------------------------------------------------------------
7198  Limit
7199    Output: foo.f1, loct1.f1, foo.f2
7200    ->  Sort
7201          Output: foo.f1, loct1.f1, foo.f2
7202          Sort Key: foo.f2
7203          ->  Merge Left Join
7204                Output: foo.f1, loct1.f1, foo.f2
7205                Merge Cond: (foo.f1 = loct1.f1)
7206                ->  Merge Append
7207                      Sort Key: foo.f1
7208                      ->  Index Scan using i_foo_f1 on public.foo
7209                            Output: foo.f1, foo.f2
7210                      ->  Foreign Scan on public.foo2
7211                            Output: foo2.f1, foo2.f2
7212                            Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
7213                ->  Index Only Scan using i_loct1_f1 on public.loct1
7214                      Output: loct1.f1
7215 (17 rows)
7216
7217 select foo.f1, loct1.f1 from foo left join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
7218  f1 | f1 
7219 ----+----
7220  10 | 10
7221  11 |   
7222  12 | 12
7223  13 |   
7224  14 | 14
7225  15 |   
7226  16 | 16
7227  17 |   
7228  18 | 18
7229  19 |   
7230 (10 rows)
7231
7232 RESET enable_hashjoin;
7233 RESET enable_nestloop;
7234 -- Test that WHERE CURRENT OF is not supported
7235 begin;
7236 declare c cursor for select * from bar where f1 = 7;
7237 fetch from c;
7238  f1 | f2  
7239 ----+-----
7240   7 | 177
7241 (1 row)
7242
7243 update bar set f2 = null where current of c;
7244 ERROR:  WHERE CURRENT OF is not supported for this table type
7245 rollback;
7246 explain (verbose, costs off)
7247 delete from foo where f1 < 5 returning *;
7248                                    QUERY PLAN                                   
7249 --------------------------------------------------------------------------------
7250  Delete on public.foo
7251    Output: foo.f1, foo.f2
7252    Delete on public.foo
7253    Foreign Delete on public.foo2
7254    ->  Index Scan using i_foo_f1 on public.foo
7255          Output: foo.ctid
7256          Index Cond: (foo.f1 < 5)
7257    ->  Foreign Delete on public.foo2
7258          Remote SQL: DELETE FROM public.loct1 WHERE ((f1 < 5)) RETURNING f1, f2
7259 (9 rows)
7260
7261 delete from foo where f1 < 5 returning *;
7262  f1 | f2 
7263 ----+----
7264   1 |  1
7265   3 |  3
7266   0 |  0
7267   2 |  2
7268   4 |  4
7269 (5 rows)
7270
7271 explain (verbose, costs off)
7272 update bar set f2 = f2 + 100 returning *;
7273                                   QUERY PLAN                                  
7274 ------------------------------------------------------------------------------
7275  Update on public.bar
7276    Output: bar.f1, bar.f2
7277    Update on public.bar
7278    Foreign Update on public.bar2
7279    ->  Seq Scan on public.bar
7280          Output: bar.f1, (bar.f2 + 100), bar.ctid
7281    ->  Foreign Update on public.bar2
7282          Remote SQL: UPDATE public.loct2 SET f2 = (f2 + 100) RETURNING f1, f2
7283 (8 rows)
7284
7285 update bar set f2 = f2 + 100 returning *;
7286  f1 | f2  
7287 ----+-----
7288   1 | 311
7289   2 | 322
7290   6 | 266
7291   3 | 333
7292   4 | 344
7293   7 | 277
7294 (6 rows)
7295
7296 -- Test that UPDATE/DELETE with inherited target works with row-level triggers
7297 CREATE TRIGGER trig_row_before
7298 BEFORE UPDATE OR DELETE ON bar2
7299 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7300 CREATE TRIGGER trig_row_after
7301 AFTER UPDATE OR DELETE ON bar2
7302 FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
7303 explain (verbose, costs off)
7304 update bar set f2 = f2 + 100;
7305                                       QUERY PLAN                                      
7306 --------------------------------------------------------------------------------------
7307  Update on public.bar
7308    Update on public.bar
7309    Foreign Update on public.bar2
7310      Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1 RETURNING f1, f2, f3
7311    ->  Seq Scan on public.bar
7312          Output: bar.f1, (bar.f2 + 100), bar.ctid
7313    ->  Foreign Scan on public.bar2
7314          Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.ctid, bar2.*
7315          Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
7316 (9 rows)
7317
7318 update bar set f2 = f2 + 100;
7319 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
7320 NOTICE:  OLD: (3,333,33),NEW: (3,433,33)
7321 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
7322 NOTICE:  OLD: (4,344,44),NEW: (4,444,44)
7323 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON bar2
7324 NOTICE:  OLD: (7,277,77),NEW: (7,377,77)
7325 NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
7326 NOTICE:  OLD: (3,333,33),NEW: (3,433,33)
7327 NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
7328 NOTICE:  OLD: (4,344,44),NEW: (4,444,44)
7329 NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON bar2
7330 NOTICE:  OLD: (7,277,77),NEW: (7,377,77)
7331 explain (verbose, costs off)
7332 delete from bar where f2 < 400;
7333                                          QUERY PLAN                                          
7334 ---------------------------------------------------------------------------------------------
7335  Delete on public.bar
7336    Delete on public.bar
7337    Foreign Delete on public.bar2
7338      Remote SQL: DELETE FROM public.loct2 WHERE ctid = $1 RETURNING f1, f2, f3
7339    ->  Seq Scan on public.bar
7340          Output: bar.ctid
7341          Filter: (bar.f2 < 400)
7342    ->  Foreign Scan on public.bar2
7343          Output: bar2.ctid, bar2.*
7344          Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 WHERE ((f2 < 400)) FOR UPDATE
7345 (10 rows)
7346
7347 delete from bar where f2 < 400;
7348 NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON bar2
7349 NOTICE:  OLD: (7,377,77)
7350 NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON bar2
7351 NOTICE:  OLD: (7,377,77)
7352 -- cleanup
7353 drop table foo cascade;
7354 NOTICE:  drop cascades to foreign table foo2
7355 drop table bar cascade;
7356 NOTICE:  drop cascades to foreign table bar2
7357 drop table loct1;
7358 drop table loct2;
7359 -- ===================================================================
7360 -- test IMPORT FOREIGN SCHEMA
7361 -- ===================================================================
7362 CREATE SCHEMA import_source;
7363 CREATE TABLE import_source.t1 (c1 int, c2 varchar NOT NULL);
7364 CREATE TABLE import_source.t2 (c1 int default 42, c2 varchar NULL, c3 text collate "POSIX");
7365 CREATE TYPE typ1 AS (m1 int, m2 varchar);
7366 CREATE TABLE import_source.t3 (c1 timestamptz default now(), c2 typ1);
7367 CREATE TABLE import_source."x 4" (c1 float8, "C 2" text, c3 varchar(42));
7368 CREATE TABLE import_source."x 5" (c1 float8);
7369 ALTER TABLE import_source."x 5" DROP COLUMN c1;
7370 CREATE TABLE import_source.t4 (c1 int) PARTITION BY RANGE (c1);
7371 CREATE TABLE import_source.t4_part PARTITION OF import_source.t4
7372   FOR VALUES FROM (1) TO (100);
7373 CREATE SCHEMA import_dest1;
7374 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest1;
7375 \det+ import_dest1.*
7376                                      List of foreign tables
7377     Schema    | Table |  Server  |                   FDW options                   | Description 
7378 --------------+-------+----------+-------------------------------------------------+-------------
7379  import_dest1 | t1    | loopback | (schema_name 'import_source', table_name 't1')  | 
7380  import_dest1 | t2    | loopback | (schema_name 'import_source', table_name 't2')  | 
7381  import_dest1 | t3    | loopback | (schema_name 'import_source', table_name 't3')  | 
7382  import_dest1 | t4    | loopback | (schema_name 'import_source', table_name 't4')  | 
7383  import_dest1 | x 4   | loopback | (schema_name 'import_source', table_name 'x 4') | 
7384  import_dest1 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') | 
7385 (6 rows)
7386
7387 \d import_dest1.*
7388                          Foreign table "import_dest1.t1"
7389  Column |       Type        | Collation | Nullable | Default |    FDW options     
7390 --------+-------------------+-----------+----------+---------+--------------------
7391  c1     | integer           |           |          |         | (column_name 'c1')
7392  c2     | character varying |           | not null |         | (column_name 'c2')
7393 Server: loopback
7394 FDW options: (schema_name 'import_source', table_name 't1')
7395
7396                          Foreign table "import_dest1.t2"
7397  Column |       Type        | Collation | Nullable | Default |    FDW options     
7398 --------+-------------------+-----------+----------+---------+--------------------
7399  c1     | integer           |           |          |         | (column_name 'c1')
7400  c2     | character varying |           |          |         | (column_name 'c2')
7401  c3     | text              | POSIX     |          |         | (column_name 'c3')
7402 Server: loopback
7403 FDW options: (schema_name 'import_source', table_name 't2')
7404
7405                              Foreign table "import_dest1.t3"
7406  Column |           Type           | Collation | Nullable | Default |    FDW options     
7407 --------+--------------------------+-----------+----------+---------+--------------------
7408  c1     | timestamp with time zone |           |          |         | (column_name 'c1')
7409  c2     | typ1                     |           |          |         | (column_name 'c2')
7410 Server: loopback
7411 FDW options: (schema_name 'import_source', table_name 't3')
7412
7413                     Foreign table "import_dest1.t4"
7414  Column |  Type   | Collation | Nullable | Default |    FDW options     
7415 --------+---------+-----------+----------+---------+--------------------
7416  c1     | integer |           |          |         | (column_name 'c1')
7417 Server: loopback
7418 FDW options: (schema_name 'import_source', table_name 't4')
7419
7420                            Foreign table "import_dest1.x 4"
7421  Column |         Type          | Collation | Nullable | Default |     FDW options     
7422 --------+-----------------------+-----------+----------+---------+---------------------
7423  c1     | double precision      |           |          |         | (column_name 'c1')
7424  C 2    | text                  |           |          |         | (column_name 'C 2')
7425  c3     | character varying(42) |           |          |         | (column_name 'c3')
7426 Server: loopback
7427 FDW options: (schema_name 'import_source', table_name 'x 4')
7428
7429                Foreign table "import_dest1.x 5"
7430  Column | Type | Collation | Nullable | Default | FDW options 
7431 --------+------+-----------+----------+---------+-------------
7432 Server: loopback
7433 FDW options: (schema_name 'import_source', table_name 'x 5')
7434
7435 -- Options
7436 CREATE SCHEMA import_dest2;
7437 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest2
7438   OPTIONS (import_default 'true');
7439 \det+ import_dest2.*
7440                                      List of foreign tables
7441     Schema    | Table |  Server  |                   FDW options                   | Description 
7442 --------------+-------+----------+-------------------------------------------------+-------------
7443  import_dest2 | t1    | loopback | (schema_name 'import_source', table_name 't1')  | 
7444  import_dest2 | t2    | loopback | (schema_name 'import_source', table_name 't2')  | 
7445  import_dest2 | t3    | loopback | (schema_name 'import_source', table_name 't3')  | 
7446  import_dest2 | t4    | loopback | (schema_name 'import_source', table_name 't4')  | 
7447  import_dest2 | x 4   | loopback | (schema_name 'import_source', table_name 'x 4') | 
7448  import_dest2 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') | 
7449 (6 rows)
7450
7451 \d import_dest2.*
7452                          Foreign table "import_dest2.t1"
7453  Column |       Type        | Collation | Nullable | Default |    FDW options     
7454 --------+-------------------+-----------+----------+---------+--------------------
7455  c1     | integer           |           |          |         | (column_name 'c1')
7456  c2     | character varying |           | not null |         | (column_name 'c2')
7457 Server: loopback
7458 FDW options: (schema_name 'import_source', table_name 't1')
7459
7460                          Foreign table "import_dest2.t2"
7461  Column |       Type        | Collation | Nullable | Default |    FDW options     
7462 --------+-------------------+-----------+----------+---------+--------------------
7463  c1     | integer           |           |          | 42      | (column_name 'c1')
7464  c2     | character varying |           |          |         | (column_name 'c2')
7465  c3     | text              | POSIX     |          |         | (column_name 'c3')
7466 Server: loopback
7467 FDW options: (schema_name 'import_source', table_name 't2')
7468
7469                              Foreign table "import_dest2.t3"
7470  Column |           Type           | Collation | Nullable | Default |    FDW options     
7471 --------+--------------------------+-----------+----------+---------+--------------------
7472  c1     | timestamp with time zone |           |          | now()   | (column_name 'c1')
7473  c2     | typ1                     |           |          |         | (column_name 'c2')
7474 Server: loopback
7475 FDW options: (schema_name 'import_source', table_name 't3')
7476
7477                     Foreign table "import_dest2.t4"
7478  Column |  Type   | Collation | Nullable | Default |    FDW options     
7479 --------+---------+-----------+----------+---------+--------------------
7480  c1     | integer |           |          |         | (column_name 'c1')
7481 Server: loopback
7482 FDW options: (schema_name 'import_source', table_name 't4')
7483
7484                            Foreign table "import_dest2.x 4"
7485  Column |         Type          | Collation | Nullable | Default |     FDW options     
7486 --------+-----------------------+-----------+----------+---------+---------------------
7487  c1     | double precision      |           |          |         | (column_name 'c1')
7488  C 2    | text                  |           |          |         | (column_name 'C 2')
7489  c3     | character varying(42) |           |          |         | (column_name 'c3')
7490 Server: loopback
7491 FDW options: (schema_name 'import_source', table_name 'x 4')
7492
7493                Foreign table "import_dest2.x 5"
7494  Column | Type | Collation | Nullable | Default | FDW options 
7495 --------+------+-----------+----------+---------+-------------
7496 Server: loopback
7497 FDW options: (schema_name 'import_source', table_name 'x 5')
7498
7499 CREATE SCHEMA import_dest3;
7500 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest3
7501   OPTIONS (import_collate 'false', import_not_null 'false');
7502 \det+ import_dest3.*
7503                                      List of foreign tables
7504     Schema    | Table |  Server  |                   FDW options                   | Description 
7505 --------------+-------+----------+-------------------------------------------------+-------------
7506  import_dest3 | t1    | loopback | (schema_name 'import_source', table_name 't1')  | 
7507  import_dest3 | t2    | loopback | (schema_name 'import_source', table_name 't2')  | 
7508  import_dest3 | t3    | loopback | (schema_name 'import_source', table_name 't3')  | 
7509  import_dest3 | t4    | loopback | (schema_name 'import_source', table_name 't4')  | 
7510  import_dest3 | x 4   | loopback | (schema_name 'import_source', table_name 'x 4') | 
7511  import_dest3 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') | 
7512 (6 rows)
7513
7514 \d import_dest3.*
7515                          Foreign table "import_dest3.t1"
7516  Column |       Type        | Collation | Nullable | Default |    FDW options     
7517 --------+-------------------+-----------+----------+---------+--------------------
7518  c1     | integer           |           |          |         | (column_name 'c1')
7519  c2     | character varying |           |          |         | (column_name 'c2')
7520 Server: loopback
7521 FDW options: (schema_name 'import_source', table_name 't1')
7522
7523                          Foreign table "import_dest3.t2"
7524  Column |       Type        | Collation | Nullable | Default |    FDW options     
7525 --------+-------------------+-----------+----------+---------+--------------------
7526  c1     | integer           |           |          |         | (column_name 'c1')
7527  c2     | character varying |           |          |         | (column_name 'c2')
7528  c3     | text              |           |          |         | (column_name 'c3')
7529 Server: loopback
7530 FDW options: (schema_name 'import_source', table_name 't2')
7531
7532                              Foreign table "import_dest3.t3"
7533  Column |           Type           | Collation | Nullable | Default |    FDW options     
7534 --------+--------------------------+-----------+----------+---------+--------------------
7535  c1     | timestamp with time zone |           |          |         | (column_name 'c1')
7536  c2     | typ1                     |           |          |         | (column_name 'c2')
7537 Server: loopback
7538 FDW options: (schema_name 'import_source', table_name 't3')
7539
7540                     Foreign table "import_dest3.t4"
7541  Column |  Type   | Collation | Nullable | Default |    FDW options     
7542 --------+---------+-----------+----------+---------+--------------------
7543  c1     | integer |           |          |         | (column_name 'c1')
7544 Server: loopback
7545 FDW options: (schema_name 'import_source', table_name 't4')
7546
7547                            Foreign table "import_dest3.x 4"
7548  Column |         Type          | Collation | Nullable | Default |     FDW options     
7549 --------+-----------------------+-----------+----------+---------+---------------------
7550  c1     | double precision      |           |          |         | (column_name 'c1')
7551  C 2    | text                  |           |          |         | (column_name 'C 2')
7552  c3     | character varying(42) |           |          |         | (column_name 'c3')
7553 Server: loopback
7554 FDW options: (schema_name 'import_source', table_name 'x 4')
7555
7556                Foreign table "import_dest3.x 5"
7557  Column | Type | Collation | Nullable | Default | FDW options 
7558 --------+------+-----------+----------+---------+-------------
7559 Server: loopback
7560 FDW options: (schema_name 'import_source', table_name 'x 5')
7561
7562 -- Check LIMIT TO and EXCEPT
7563 CREATE SCHEMA import_dest4;
7564 IMPORT FOREIGN SCHEMA import_source LIMIT TO (t1, nonesuch)
7565   FROM SERVER loopback INTO import_dest4;
7566 \det+ import_dest4.*
7567                                      List of foreign tables
7568     Schema    | Table |  Server  |                  FDW options                   | Description 
7569 --------------+-------+----------+------------------------------------------------+-------------
7570  import_dest4 | t1    | loopback | (schema_name 'import_source', table_name 't1') | 
7571 (1 row)
7572
7573 IMPORT FOREIGN SCHEMA import_source EXCEPT (t1, "x 4", nonesuch)
7574   FROM SERVER loopback INTO import_dest4;
7575 \det+ import_dest4.*
7576                                      List of foreign tables
7577     Schema    | Table |  Server  |                   FDW options                   | Description 
7578 --------------+-------+----------+-------------------------------------------------+-------------
7579  import_dest4 | t1    | loopback | (schema_name 'import_source', table_name 't1')  | 
7580  import_dest4 | t2    | loopback | (schema_name 'import_source', table_name 't2')  | 
7581  import_dest4 | t3    | loopback | (schema_name 'import_source', table_name 't3')  | 
7582  import_dest4 | t4    | loopback | (schema_name 'import_source', table_name 't4')  | 
7583  import_dest4 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') | 
7584 (5 rows)
7585
7586 -- Assorted error cases
7587 IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest4;
7588 ERROR:  relation "t1" already exists
7589 CONTEXT:  importing foreign table "t1"
7590 IMPORT FOREIGN SCHEMA nonesuch FROM SERVER loopback INTO import_dest4;
7591 ERROR:  schema "nonesuch" is not present on foreign server "loopback"
7592 IMPORT FOREIGN SCHEMA nonesuch FROM SERVER loopback INTO notthere;
7593 ERROR:  schema "notthere" does not exist
7594 IMPORT FOREIGN SCHEMA nonesuch FROM SERVER nowhere INTO notthere;
7595 ERROR:  server "nowhere" does not exist
7596 -- Check case of a type present only on the remote server.
7597 -- We can fake this by dropping the type locally in our transaction.
7598 CREATE TYPE "Colors" AS ENUM ('red', 'green', 'blue');
7599 CREATE TABLE import_source.t5 (c1 int, c2 text collate "C", "Col" "Colors");
7600 CREATE SCHEMA import_dest5;
7601 BEGIN;
7602 DROP TYPE "Colors" CASCADE;
7603 NOTICE:  drop cascades to table import_source.t5 column Col
7604 IMPORT FOREIGN SCHEMA import_source LIMIT TO (t5)
7605   FROM SERVER loopback INTO import_dest5;  -- ERROR
7606 ERROR:  type "public.Colors" does not exist
7607 LINE 4:   "Col" public."Colors" OPTIONS (column_name 'Col')
7608                 ^
7609 QUERY:  CREATE FOREIGN TABLE t5 (
7610   c1 integer OPTIONS (column_name 'c1'),
7611   c2 text OPTIONS (column_name 'c2') COLLATE pg_catalog."C",
7612   "Col" public."Colors" OPTIONS (column_name 'Col')
7613 ) SERVER loopback
7614 OPTIONS (schema_name 'import_source', table_name 't5');
7615 CONTEXT:  importing foreign table "t5"
7616 ROLLBACK;
7617 BEGIN;
7618 CREATE SERVER fetch101 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( fetch_size '101' );
7619 SELECT count(*)
7620 FROM pg_foreign_server
7621 WHERE srvname = 'fetch101'
7622 AND srvoptions @> array['fetch_size=101'];
7623  count 
7624 -------
7625      1
7626 (1 row)
7627
7628 ALTER SERVER fetch101 OPTIONS( SET fetch_size '202' );
7629 SELECT count(*)
7630 FROM pg_foreign_server
7631 WHERE srvname = 'fetch101'
7632 AND srvoptions @> array['fetch_size=101'];
7633  count 
7634 -------
7635      0
7636 (1 row)
7637
7638 SELECT count(*)
7639 FROM pg_foreign_server
7640 WHERE srvname = 'fetch101'
7641 AND srvoptions @> array['fetch_size=202'];
7642  count 
7643 -------
7644      1
7645 (1 row)
7646
7647 CREATE FOREIGN TABLE table30000 ( x int ) SERVER fetch101 OPTIONS ( fetch_size '30000' );
7648 SELECT COUNT(*)
7649 FROM pg_foreign_table
7650 WHERE ftrelid = 'table30000'::regclass
7651 AND ftoptions @> array['fetch_size=30000'];
7652  count 
7653 -------
7654      1
7655 (1 row)
7656
7657 ALTER FOREIGN TABLE table30000 OPTIONS ( SET fetch_size '60000');
7658 SELECT COUNT(*)
7659 FROM pg_foreign_table
7660 WHERE ftrelid = 'table30000'::regclass
7661 AND ftoptions @> array['fetch_size=30000'];
7662  count 
7663 -------
7664      0
7665 (1 row)
7666
7667 SELECT COUNT(*)
7668 FROM pg_foreign_table
7669 WHERE ftrelid = 'table30000'::regclass
7670 AND ftoptions @> array['fetch_size=60000'];
7671  count 
7672 -------
7673      1
7674 (1 row)
7675
7676 ROLLBACK;
7677 -- ===================================================================
7678 -- test partition-wise-joins
7679 -- ===================================================================
7680 SET enable_partition_wise_join=on;
7681 CREATE TABLE fprt1 (a int, b int, c varchar) PARTITION BY RANGE(a);
7682 CREATE TABLE fprt1_p1 (LIKE fprt1);
7683 CREATE TABLE fprt1_p2 (LIKE fprt1);
7684 INSERT INTO fprt1_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 2) i;
7685 INSERT INTO fprt1_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 2) i;
7686 CREATE FOREIGN TABLE ftprt1_p1 PARTITION OF fprt1 FOR VALUES FROM (0) TO (250)
7687         SERVER loopback OPTIONS (table_name 'fprt1_p1', use_remote_estimate 'true');
7688 CREATE FOREIGN TABLE ftprt1_p2 PARTITION OF fprt1 FOR VALUES FROM (250) TO (500)
7689         SERVER loopback OPTIONS (TABLE_NAME 'fprt1_p2');
7690 ANALYZE fprt1;
7691 ANALYZE fprt1_p1;
7692 ANALYZE fprt1_p2;
7693 CREATE TABLE fprt2 (a int, b int, c varchar) PARTITION BY RANGE(b);
7694 CREATE TABLE fprt2_p1 (LIKE fprt2);
7695 CREATE TABLE fprt2_p2 (LIKE fprt2);
7696 INSERT INTO fprt2_p1 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(0, 249, 3) i;
7697 INSERT INTO fprt2_p2 SELECT i, i, to_char(i/50, 'FM0000') FROM generate_series(250, 499, 3) i;
7698 CREATE FOREIGN TABLE ftprt2_p1 PARTITION OF fprt2 FOR VALUES FROM (0) TO (250)
7699         SERVER loopback OPTIONS (table_name 'fprt2_p1', use_remote_estimate 'true');
7700 CREATE FOREIGN TABLE ftprt2_p2 PARTITION OF fprt2 FOR VALUES FROM (250) TO (500)
7701         SERVER loopback OPTIONS (table_name 'fprt2_p2', use_remote_estimate 'true');
7702 ANALYZE fprt2;
7703 ANALYZE fprt2_p1;
7704 ANALYZE fprt2_p2;
7705 -- inner join three tables
7706 EXPLAIN (COSTS OFF)
7707 SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3;
7708                                                      QUERY PLAN                                                     
7709 --------------------------------------------------------------------------------------------------------------------
7710  Sort
7711    Sort Key: t1.a, t3.c
7712    ->  Append
7713          ->  Foreign Scan
7714                Relations: ((public.ftprt1_p1 t1) INNER JOIN (public.ftprt2_p1 t2)) INNER JOIN (public.ftprt1_p1 t3)
7715          ->  Foreign Scan
7716                Relations: ((public.ftprt1_p2 t1) INNER JOIN (public.ftprt2_p2 t2)) INNER JOIN (public.ftprt1_p2 t3)
7717 (7 rows)
7718
7719 SELECT t1.a,t2.b,t3.c FROM fprt1 t1 INNER JOIN fprt2 t2 ON (t1.a = t2.b) INNER JOIN fprt1 t3 ON (t2.b = t3.a) WHERE t1.a % 25 =0 ORDER BY 1,2,3;
7720   a  |  b  |  c   
7721 -----+-----+------
7722    0 |   0 | 0000
7723  150 | 150 | 0003
7724  250 | 250 | 0005
7725  400 | 400 | 0008
7726 (4 rows)
7727
7728 -- left outer join + nullable clasue
7729 EXPLAIN (COSTS OFF)
7730 SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3;
7731                                     QUERY PLAN                                     
7732 -----------------------------------------------------------------------------------
7733  Sort
7734    Sort Key: t1.a, ftprt2_p1.b, ftprt2_p1.c
7735    ->  Append
7736          ->  Foreign Scan
7737                Relations: (public.ftprt1_p1 t1) LEFT JOIN (public.ftprt2_p1 fprt2)
7738 (5 rows)
7739
7740 SELECT t1.a,t2.b,t2.c FROM fprt1 t1 LEFT JOIN (SELECT * FROM fprt2 WHERE a < 10) t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a < 10 ORDER BY 1,2,3;
7741  a | b |  c   
7742 ---+---+------
7743  0 | 0 | 0000
7744  2 |   | 
7745  4 |   | 
7746  6 | 6 | 0000
7747  8 |   | 
7748 (5 rows)
7749
7750 -- with whole-row reference
7751 EXPLAIN (COSTS OFF)
7752 SELECT t1,t2 FROM fprt1 t1 JOIN fprt2 t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a % 25 =0 ORDER BY 1,2;
7753                                    QUERY PLAN                                    
7754 ---------------------------------------------------------------------------------
7755  Sort
7756    Sort Key: ((t1.*)::fprt1), ((t2.*)::fprt2)
7757    ->  Append
7758          ->  Foreign Scan
7759                Relations: (public.ftprt1_p1 t1) INNER JOIN (public.ftprt2_p1 t2)
7760          ->  Foreign Scan
7761                Relations: (public.ftprt1_p2 t1) INNER JOIN (public.ftprt2_p2 t2)
7762 (7 rows)
7763
7764 SELECT t1,t2 FROM fprt1 t1 JOIN fprt2 t2 ON (t1.a = t2.b and t1.b = t2.a) WHERE t1.a % 25 =0 ORDER BY 1,2;
7765        t1       |       t2       
7766 ----------------+----------------
7767  (0,0,0000)     | (0,0,0000)
7768  (150,150,0003) | (150,150,0003)
7769  (250,250,0005) | (250,250,0005)
7770  (400,400,0008) | (400,400,0008)
7771 (4 rows)
7772
7773 -- join with lateral reference
7774 EXPLAIN (COSTS OFF)
7775 SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2;
7776                                    QUERY PLAN                                    
7777 ---------------------------------------------------------------------------------
7778  Sort
7779    Sort Key: t1.a, t1.b
7780    ->  Append
7781          ->  Foreign Scan
7782                Relations: (public.ftprt1_p1 t1) INNER JOIN (public.ftprt2_p1 t2)
7783          ->  Foreign Scan
7784                Relations: (public.ftprt1_p2 t1) INNER JOIN (public.ftprt2_p2 t2)
7785 (7 rows)
7786
7787 SELECT t1.a,t1.b FROM fprt1 t1, LATERAL (SELECT t2.a, t2.b FROM fprt2 t2 WHERE t1.a = t2.b AND t1.b = t2.a) q WHERE t1.a%25 = 0 ORDER BY 1,2;
7788   a  |  b  
7789 -----+-----
7790    0 |   0
7791  150 | 150
7792  250 | 250
7793  400 | 400
7794 (4 rows)
7795
7796 RESET enable_partition_wise_join;