mirror of
				https://github.com/postgres/postgres.git
				synced 2025-10-31 10:30:33 +03:00 
			
		
		
		
	Make separate columns "Collation", "Nullable", "Default". Reviewed-by: Kuntal Ghosh <kuntalghosh.2007@gmail.com>
		
			
				
	
	
		
			6975 lines
		
	
	
		
			344 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			6975 lines
		
	
	
		
			344 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| -- ===================================================================
 | |
| -- create FDW objects
 | |
| -- ===================================================================
 | |
| CREATE EXTENSION postgres_fdw;
 | |
| CREATE SERVER testserver1 FOREIGN DATA WRAPPER postgres_fdw;
 | |
| DO $d$
 | |
|     BEGIN
 | |
|         EXECUTE $$CREATE SERVER loopback FOREIGN DATA WRAPPER postgres_fdw
 | |
|             OPTIONS (dbname '$$||current_database()||$$',
 | |
|                      port '$$||current_setting('port')||$$'
 | |
|             )$$;
 | |
|         EXECUTE $$CREATE SERVER loopback2 FOREIGN DATA WRAPPER postgres_fdw
 | |
|             OPTIONS (dbname '$$||current_database()||$$',
 | |
|                      port '$$||current_setting('port')||$$'
 | |
|             )$$;
 | |
|     END;
 | |
| $d$;
 | |
| CREATE USER MAPPING FOR public SERVER testserver1
 | |
| 	OPTIONS (user 'value', password 'value');
 | |
| CREATE USER MAPPING FOR CURRENT_USER SERVER loopback;
 | |
| CREATE USER MAPPING FOR CURRENT_USER SERVER loopback2;
 | |
| -- ===================================================================
 | |
| -- create objects used through FDW loopback server
 | |
| -- ===================================================================
 | |
| CREATE TYPE user_enum AS ENUM ('foo', 'bar', 'buz');
 | |
| CREATE SCHEMA "S 1";
 | |
| CREATE TABLE "S 1"."T 1" (
 | |
| 	"C 1" int NOT NULL,
 | |
| 	c2 int NOT NULL,
 | |
| 	c3 text,
 | |
| 	c4 timestamptz,
 | |
| 	c5 timestamp,
 | |
| 	c6 varchar(10),
 | |
| 	c7 char(10),
 | |
| 	c8 user_enum,
 | |
| 	CONSTRAINT t1_pkey PRIMARY KEY ("C 1")
 | |
| );
 | |
| CREATE TABLE "S 1"."T 2" (
 | |
| 	c1 int NOT NULL,
 | |
| 	c2 text,
 | |
| 	CONSTRAINT t2_pkey PRIMARY KEY (c1)
 | |
| );
 | |
| CREATE TABLE "S 1"."T 3" (
 | |
| 	c1 int NOT NULL,
 | |
| 	c2 int NOT NULL,
 | |
| 	c3 text,
 | |
| 	CONSTRAINT t3_pkey PRIMARY KEY (c1)
 | |
| );
 | |
| CREATE TABLE "S 1"."T 4" (
 | |
| 	c1 int NOT NULL,
 | |
| 	c2 int NOT NULL,
 | |
| 	c3 text,
 | |
| 	CONSTRAINT t4_pkey PRIMARY KEY (c1)
 | |
| );
 | |
| INSERT INTO "S 1"."T 1"
 | |
| 	SELECT id,
 | |
| 	       id % 10,
 | |
| 	       to_char(id, 'FM00000'),
 | |
| 	       '1970-01-01'::timestamptz + ((id % 100) || ' days')::interval,
 | |
| 	       '1970-01-01'::timestamp + ((id % 100) || ' days')::interval,
 | |
| 	       id % 10,
 | |
| 	       id % 10,
 | |
| 	       'foo'::user_enum
 | |
| 	FROM generate_series(1, 1000) id;
 | |
| INSERT INTO "S 1"."T 2"
 | |
| 	SELECT id,
 | |
| 	       'AAA' || to_char(id, 'FM000')
 | |
| 	FROM generate_series(1, 100) id;
 | |
| INSERT INTO "S 1"."T 3"
 | |
| 	SELECT id,
 | |
| 	       id + 1,
 | |
| 	       'AAA' || to_char(id, 'FM000')
 | |
| 	FROM generate_series(1, 100) id;
 | |
| DELETE FROM "S 1"."T 3" WHERE c1 % 2 != 0;	-- delete for outer join tests
 | |
| INSERT INTO "S 1"."T 4"
 | |
| 	SELECT id,
 | |
| 	       id + 1,
 | |
| 	       'AAA' || to_char(id, 'FM000')
 | |
| 	FROM generate_series(1, 100) id;
 | |
| DELETE FROM "S 1"."T 4" WHERE c1 % 3 != 0;	-- delete for outer join tests
 | |
| ANALYZE "S 1"."T 1";
 | |
| ANALYZE "S 1"."T 2";
 | |
| ANALYZE "S 1"."T 3";
 | |
| ANALYZE "S 1"."T 4";
 | |
| -- ===================================================================
 | |
| -- create foreign tables
 | |
| -- ===================================================================
 | |
| CREATE FOREIGN TABLE ft1 (
 | |
| 	c0 int,
 | |
| 	c1 int NOT NULL,
 | |
| 	c2 int NOT NULL,
 | |
| 	c3 text,
 | |
| 	c4 timestamptz,
 | |
| 	c5 timestamp,
 | |
| 	c6 varchar(10),
 | |
| 	c7 char(10) default 'ft1',
 | |
| 	c8 user_enum
 | |
| ) SERVER loopback;
 | |
| ALTER FOREIGN TABLE ft1 DROP COLUMN c0;
 | |
| CREATE FOREIGN TABLE ft2 (
 | |
| 	c1 int NOT NULL,
 | |
| 	c2 int NOT NULL,
 | |
| 	cx int,
 | |
| 	c3 text,
 | |
| 	c4 timestamptz,
 | |
| 	c5 timestamp,
 | |
| 	c6 varchar(10),
 | |
| 	c7 char(10) default 'ft2',
 | |
| 	c8 user_enum
 | |
| ) SERVER loopback;
 | |
| ALTER FOREIGN TABLE ft2 DROP COLUMN cx;
 | |
| CREATE FOREIGN TABLE ft4 (
 | |
| 	c1 int NOT NULL,
 | |
| 	c2 int NOT NULL,
 | |
| 	c3 text
 | |
| ) SERVER loopback OPTIONS (schema_name 'S 1', table_name 'T 3');
 | |
| CREATE FOREIGN TABLE ft5 (
 | |
| 	c1 int NOT NULL,
 | |
| 	c2 int NOT NULL,
 | |
| 	c3 text
 | |
| ) SERVER loopback OPTIONS (schema_name 'S 1', table_name 'T 4');
 | |
| CREATE FOREIGN TABLE ft6 (
 | |
| 	c1 int NOT NULL,
 | |
| 	c2 int NOT NULL,
 | |
| 	c3 text
 | |
| ) SERVER loopback2 OPTIONS (schema_name 'S 1', table_name 'T 4');
 | |
| -- A table with oids. CREATE FOREIGN TABLE doesn't support the
 | |
| -- WITH OIDS option, but ALTER does.
 | |
| CREATE FOREIGN TABLE ft_pg_type (
 | |
| 	typname name,
 | |
| 	typlen smallint
 | |
| ) SERVER loopback OPTIONS (schema_name 'pg_catalog', table_name 'pg_type');
 | |
| ALTER TABLE ft_pg_type SET WITH OIDS;
 | |
| -- ===================================================================
 | |
| -- tests for validator
 | |
| -- ===================================================================
 | |
| -- requiressl, krbsrvname and gsslib are omitted because they depend on
 | |
| -- configure options
 | |
| ALTER SERVER testserver1 OPTIONS (
 | |
| 	use_remote_estimate 'false',
 | |
| 	updatable 'true',
 | |
| 	fdw_startup_cost '123.456',
 | |
| 	fdw_tuple_cost '0.123',
 | |
| 	service 'value',
 | |
| 	connect_timeout 'value',
 | |
| 	dbname 'value',
 | |
| 	host 'value',
 | |
| 	hostaddr 'value',
 | |
| 	port 'value',
 | |
| 	--client_encoding 'value',
 | |
| 	application_name 'value',
 | |
| 	--fallback_application_name 'value',
 | |
| 	keepalives 'value',
 | |
| 	keepalives_idle 'value',
 | |
| 	keepalives_interval 'value',
 | |
| 	-- requiressl 'value',
 | |
| 	sslcompression 'value',
 | |
| 	sslmode 'value',
 | |
| 	sslcert 'value',
 | |
| 	sslkey 'value',
 | |
| 	sslrootcert 'value',
 | |
| 	sslcrl 'value'
 | |
| 	--requirepeer 'value',
 | |
| 	-- krbsrvname 'value',
 | |
| 	-- gsslib 'value',
 | |
| 	--replication 'value'
 | |
| );
 | |
| -- Error, invalid list syntax
 | |
| ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo; bar');
 | |
| ERROR:  parameter "extensions" must be a list of extension names
 | |
| -- OK but gets a warning
 | |
| ALTER SERVER testserver1 OPTIONS (ADD extensions 'foo, bar');
 | |
| WARNING:  extension "foo" is not installed
 | |
| WARNING:  extension "bar" is not installed
 | |
| ALTER SERVER testserver1 OPTIONS (DROP extensions);
 | |
| ALTER USER MAPPING FOR public SERVER testserver1
 | |
| 	OPTIONS (DROP user, DROP password);
 | |
| ALTER FOREIGN TABLE ft1 OPTIONS (schema_name 'S 1', table_name 'T 1');
 | |
| ALTER FOREIGN TABLE ft2 OPTIONS (schema_name 'S 1', table_name 'T 1');
 | |
| ALTER FOREIGN TABLE ft1 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
 | |
| ALTER FOREIGN TABLE ft2 ALTER COLUMN c1 OPTIONS (column_name 'C 1');
 | |
| \det+
 | |
|                                       List of foreign tables
 | |
|  Schema |   Table    |  Server   |                   FDW Options                    | Description 
 | |
| --------+------------+-----------+--------------------------------------------------+-------------
 | |
|  public | ft1        | loopback  | (schema_name 'S 1', table_name 'T 1')            | 
 | |
|  public | ft2        | loopback  | (schema_name 'S 1', table_name 'T 1')            | 
 | |
|  public | ft4        | loopback  | (schema_name 'S 1', table_name 'T 3')            | 
 | |
|  public | ft5        | loopback  | (schema_name 'S 1', table_name 'T 4')            | 
 | |
|  public | ft6        | loopback2 | (schema_name 'S 1', table_name 'T 4')            | 
 | |
|  public | ft_pg_type | loopback  | (schema_name 'pg_catalog', table_name 'pg_type') | 
 | |
| (6 rows)
 | |
| 
 | |
| -- Now we should be able to run ANALYZE.
 | |
| -- To exercise multiple code paths, we use local stats on ft1
 | |
| -- and remote-estimate mode on ft2.
 | |
| ANALYZE ft1;
 | |
| ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true');
 | |
| -- ===================================================================
 | |
| -- simple queries
 | |
| -- ===================================================================
 | |
| -- single table without alias
 | |
| EXPLAIN (COSTS OFF) SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
 | |
|         QUERY PLAN         
 | |
| ---------------------------
 | |
|  Limit
 | |
|    ->  Foreign Scan on ft1
 | |
| (2 rows)
 | |
| 
 | |
| SELECT * FROM ft1 ORDER BY c3, c1 OFFSET 100 LIMIT 10;
 | |
|  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| -----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
|  102 |  2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
 | |
|  103 |  3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
 | |
|  104 |  4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
 | |
|  105 |  5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
 | |
|  106 |  6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  107 |  7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|  108 |  8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|  109 |  9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
 | |
|  110 |  0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0  | 0          | foo
 | |
| (10 rows)
 | |
| 
 | |
| -- single table with alias - also test that tableoid sort is not pushed to remote side
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
 | |
|                                      QUERY PLAN                                      
 | |
| -------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
 | |
|    ->  Sort
 | |
|          Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
 | |
|          Sort Key: t1.c3, t1.c1, t1.tableoid
 | |
|          ->  Foreign Scan on public.ft1 t1
 | |
|                Output: c1, c2, c3, c4, c5, c6, c7, c8, tableoid
 | |
|                Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
 | |
| (8 rows)
 | |
| 
 | |
| SELECT * FROM ft1 t1 ORDER BY t1.c3, t1.c1, t1.tableoid OFFSET 100 LIMIT 10;
 | |
|  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| -----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
|  102 |  2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
 | |
|  103 |  3 | 00103 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
 | |
|  104 |  4 | 00104 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
 | |
|  105 |  5 | 00105 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
 | |
|  106 |  6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  107 |  7 | 00107 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|  108 |  8 | 00108 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|  109 |  9 | 00109 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
 | |
|  110 |  0 | 00110 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0  | 0          | foo
 | |
| (10 rows)
 | |
| 
 | |
| -- whole-row reference
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
 | |
|                                                            QUERY PLAN                                                           
 | |
| --------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.*, c3, c1
 | |
|    ->  Foreign Scan on public.ft1 t1
 | |
|          Output: t1.*, c3, c1
 | |
|          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
 | |
| (5 rows)
 | |
| 
 | |
| SELECT t1 FROM ft1 t1 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
 | |
|                                              t1                                             
 | |
| --------------------------------------------------------------------------------------------
 | |
|  (101,1,00101,"Fri Jan 02 00:00:00 1970 PST","Fri Jan 02 00:00:00 1970",1,"1         ",foo)
 | |
|  (102,2,00102,"Sat Jan 03 00:00:00 1970 PST","Sat Jan 03 00:00:00 1970",2,"2         ",foo)
 | |
|  (103,3,00103,"Sun Jan 04 00:00:00 1970 PST","Sun Jan 04 00:00:00 1970",3,"3         ",foo)
 | |
|  (104,4,00104,"Mon Jan 05 00:00:00 1970 PST","Mon Jan 05 00:00:00 1970",4,"4         ",foo)
 | |
|  (105,5,00105,"Tue Jan 06 00:00:00 1970 PST","Tue Jan 06 00:00:00 1970",5,"5         ",foo)
 | |
|  (106,6,00106,"Wed Jan 07 00:00:00 1970 PST","Wed Jan 07 00:00:00 1970",6,"6         ",foo)
 | |
|  (107,7,00107,"Thu Jan 08 00:00:00 1970 PST","Thu Jan 08 00:00:00 1970",7,"7         ",foo)
 | |
|  (108,8,00108,"Fri Jan 09 00:00:00 1970 PST","Fri Jan 09 00:00:00 1970",8,"8         ",foo)
 | |
|  (109,9,00109,"Sat Jan 10 00:00:00 1970 PST","Sat Jan 10 00:00:00 1970",9,"9         ",foo)
 | |
|  (110,0,00110,"Sun Jan 11 00:00:00 1970 PST","Sun Jan 11 00:00:00 1970",0,"0         ",foo)
 | |
| (10 rows)
 | |
| 
 | |
| -- empty result
 | |
| SELECT * FROM ft1 WHERE false;
 | |
|  c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 
 | |
| ----+----+----+----+----+----+----+----
 | |
| (0 rows)
 | |
| 
 | |
| -- with WHERE clause
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1';
 | |
|                                                                    QUERY PLAN                                                                   
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    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))
 | |
| (3 rows)
 | |
| 
 | |
| SELECT * FROM ft1 t1 WHERE t1.c1 = 101 AND t1.c6 = '1' AND t1.c7 >= '1';
 | |
|  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| -----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
| (1 row)
 | |
| 
 | |
| -- with FOR UPDATE/SHARE
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE;
 | |
|                                                    QUERY PLAN                                                   
 | |
| ----------------------------------------------------------------------------------------------------------------
 | |
|  LockRows
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
 | |
|    ->  Foreign Scan on public.ft1 t1
 | |
|          Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
 | |
|          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 101)) FOR UPDATE
 | |
| (5 rows)
 | |
| 
 | |
| SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE;
 | |
|  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| -----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  101 |  1 | 00101 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
| (1 row)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE;
 | |
|                                                   QUERY PLAN                                                   
 | |
| ---------------------------------------------------------------------------------------------------------------
 | |
|  LockRows
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
 | |
|    ->  Foreign Scan on public.ft1 t1
 | |
|          Output: c1, c2, c3, c4, c5, c6, c7, c8, t1.*
 | |
|          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 102)) FOR SHARE
 | |
| (5 rows)
 | |
| 
 | |
| SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE;
 | |
|  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| -----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  102 |  2 | 00102 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
 | |
| (1 row)
 | |
| 
 | |
| -- aggregate
 | |
| SELECT COUNT(*) FROM ft1 t1;
 | |
|  count 
 | |
| -------
 | |
|   1000
 | |
| (1 row)
 | |
| 
 | |
| -- subquery
 | |
| SELECT * FROM ft1 t1 WHERE t1.c3 IN (SELECT c3 FROM ft2 t2 WHERE c1 <= 10) ORDER BY c1;
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
|   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
 | |
|   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
 | |
|   4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
 | |
|   5 |  5 | 00005 | Tue Jan 06 00:00:00 1970 PST | Tue Jan 06 00:00:00 1970 | 5  | 5          | foo
 | |
|   6 |  6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|   7 |  7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   8 |  8 | 00008 | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   9 |  9 | 00009 | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | 9          | foo
 | |
|  10 |  0 | 00010 | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0  | 0          | foo
 | |
| (10 rows)
 | |
| 
 | |
| -- subquery+MAX
 | |
| SELECT * FROM ft1 t1 WHERE t1.c3 = (SELECT MAX(c3) FROM ft2 t2) ORDER BY c1;
 | |
|   c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ------+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  1000 |  0 | 01000 | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0  | 0          | foo
 | |
| (1 row)
 | |
| 
 | |
| -- used in CTE
 | |
| WITH t1 AS (SELECT * FROM ft1 WHERE c1 <= 10) SELECT t2.c1, t2.c2, t2.c3, t2.c4 FROM t1, ft2 t2 WHERE t1.c1 = t2.c1 ORDER BY t1.c1;
 | |
|  c1 | c2 |  c3   |              c4              
 | |
| ----+----+-------+------------------------------
 | |
|   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST
 | |
|   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST
 | |
|   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST
 | |
|   4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST
 | |
|   5 |  5 | 00005 | Tue Jan 06 00:00:00 1970 PST
 | |
|   6 |  6 | 00006 | Wed Jan 07 00:00:00 1970 PST
 | |
|   7 |  7 | 00007 | Thu Jan 08 00:00:00 1970 PST
 | |
|   8 |  8 | 00008 | Fri Jan 09 00:00:00 1970 PST
 | |
|   9 |  9 | 00009 | Sat Jan 10 00:00:00 1970 PST
 | |
|  10 |  0 | 00010 | Sun Jan 11 00:00:00 1970 PST
 | |
| (10 rows)
 | |
| 
 | |
| -- fixed values
 | |
| SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1;
 | |
|  ?column? | ?column? 
 | |
| ----------+----------
 | |
|  fixed    | 
 | |
| (1 row)
 | |
| 
 | |
| -- Test forcing the remote server to produce sorted data for a merge join.
 | |
| SET enable_hashjoin TO false;
 | |
| SET enable_nestloop TO false;
 | |
| -- inner join; expressions in the clauses appear in the equivalence class list
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| 	SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10;
 | |
|                                       QUERY PLAN                                       
 | |
| ---------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2."C 1"
 | |
|    ->  Merge Join
 | |
|          Output: t1.c1, t2."C 1"
 | |
|          Merge Cond: (t1.c1 = t2."C 1")
 | |
|          ->  Foreign Scan on public.ft2 t1
 | |
|                Output: t1.c1
 | |
|                Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
 | |
|          ->  Index Only Scan using t1_pkey on "S 1"."T 1" t2
 | |
|                Output: t2."C 1"
 | |
| (10 rows)
 | |
| 
 | |
| SELECT t1.c1, t2."C 1" FROM ft2 t1 JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10;
 | |
|  c1  | C 1 
 | |
| -----+-----
 | |
|  101 | 101
 | |
|  102 | 102
 | |
|  103 | 103
 | |
|  104 | 104
 | |
|  105 | 105
 | |
|  106 | 106
 | |
|  107 | 107
 | |
|  108 | 108
 | |
|  109 | 109
 | |
|  110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| -- outer join; expressions in the clauses do not appear in equivalence class
 | |
| -- list but no output change as compared to the previous query
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| 	SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10;
 | |
|                                       QUERY PLAN                                       
 | |
| ---------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2."C 1"
 | |
|    ->  Merge Left Join
 | |
|          Output: t1.c1, t2."C 1"
 | |
|          Merge Cond: (t1.c1 = t2."C 1")
 | |
|          ->  Foreign Scan on public.ft2 t1
 | |
|                Output: t1.c1
 | |
|                Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
 | |
|          ->  Index Only Scan using t1_pkey on "S 1"."T 1" t2
 | |
|                Output: t2."C 1"
 | |
| (10 rows)
 | |
| 
 | |
| SELECT t1.c1, t2."C 1" FROM ft2 t1 LEFT JOIN "S 1"."T 1" t2 ON (t1.c1 = t2."C 1") OFFSET 100 LIMIT 10;
 | |
|  c1  | C 1 
 | |
| -----+-----
 | |
|  101 | 101
 | |
|  102 | 102
 | |
|  103 | 103
 | |
|  104 | 104
 | |
|  105 | 105
 | |
|  106 | 106
 | |
|  107 | 107
 | |
|  108 | 108
 | |
|  109 | 109
 | |
|  110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| -- A join between local table and foreign join. ORDER BY clause is added to the
 | |
| -- foreign join so that the local table can be joined using merge join strategy.
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| 	SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
 | |
|                                                                        QUERY PLAN                                                                        
 | |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1."C 1"
 | |
|    ->  Merge Right Join
 | |
|          Output: t1."C 1"
 | |
|          Merge Cond: (t3.c1 = t1."C 1")
 | |
|          ->  Foreign Scan
 | |
|                Output: t3.c1
 | |
|                Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
 | |
|                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
 | |
|          ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
 | |
|                Output: t1."C 1"
 | |
| (11 rows)
 | |
| 
 | |
| SELECT t1."C 1" FROM "S 1"."T 1" t1 left join ft1 t2 join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
 | |
|  C 1 
 | |
| -----
 | |
|  101
 | |
|  102
 | |
|  103
 | |
|  104
 | |
|  105
 | |
|  106
 | |
|  107
 | |
|  108
 | |
|  109
 | |
|  110
 | |
| (10 rows)
 | |
| 
 | |
| -- Test similar to above, except that the full join prevents any equivalence
 | |
| -- classes from being merged. This produces single relation equivalence classes
 | |
| -- included in join restrictions.
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| 	SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
 | |
|                                                                             QUERY PLAN                                                                            
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1."C 1", t2.c1, t3.c1
 | |
|    ->  Merge Right Join
 | |
|          Output: t1."C 1", t2.c1, t3.c1
 | |
|          Merge Cond: (t3.c1 = t1."C 1")
 | |
|          ->  Foreign Scan
 | |
|                Output: t3.c1, t2.c1
 | |
|                Relations: (public.ft2 t3) LEFT JOIN (public.ft1 t2)
 | |
|                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
 | |
|          ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
 | |
|                Output: t1."C 1"
 | |
| (11 rows)
 | |
| 
 | |
| SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 left join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
 | |
|  C 1 | c1  | c1  
 | |
| -----+-----+-----
 | |
|  101 | 101 | 101
 | |
|  102 | 102 | 102
 | |
|  103 | 103 | 103
 | |
|  104 | 104 | 104
 | |
|  105 | 105 | 105
 | |
|  106 | 106 | 106
 | |
|  107 | 107 | 107
 | |
|  108 | 108 | 108
 | |
|  109 | 109 | 109
 | |
|  110 | 110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| -- Test similar to above with all full outer joins
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| 	SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
 | |
|                                                                             QUERY PLAN                                                                            
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1."C 1", t2.c1, t3.c1
 | |
|    ->  Merge Full Join
 | |
|          Output: t1."C 1", t2.c1, t3.c1
 | |
|          Merge Cond: (t3.c1 = t1."C 1")
 | |
|          ->  Foreign Scan
 | |
|                Output: t2.c1, t3.c1
 | |
|                Relations: (public.ft1 t2) FULL JOIN (public.ft2 t3)
 | |
|                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
 | |
|          ->  Index Only Scan using t1_pkey on "S 1"."T 1" t1
 | |
|                Output: t1."C 1"
 | |
| (11 rows)
 | |
| 
 | |
| SELECT t1."C 1", t2.c1, t3.c1 FROM "S 1"."T 1" t1 full join ft1 t2 full join ft2 t3 on (t2.c1 = t3.c1) on (t3.c1 = t1."C 1") OFFSET 100 LIMIT 10;
 | |
|  C 1 | c1  | c1  
 | |
| -----+-----+-----
 | |
|  101 | 101 | 101
 | |
|  102 | 102 | 102
 | |
|  103 | 103 | 103
 | |
|  104 | 104 | 104
 | |
|  105 | 105 | 105
 | |
|  106 | 106 | 106
 | |
|  107 | 107 | 107
 | |
|  108 | 108 | 108
 | |
|  109 | 109 | 109
 | |
|  110 | 110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| RESET enable_hashjoin;
 | |
| RESET enable_nestloop;
 | |
| -- ===================================================================
 | |
| -- WHERE with remotely-executable conditions
 | |
| -- ===================================================================
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 1;         -- Var, OpExpr(b), Const
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE t1.c1 = 100 AND t1.c2 = 0; -- BoolExpr
 | |
|                                                   QUERY PLAN                                                  
 | |
| --------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 100)) AND ((c2 = 0))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NULL;        -- NullTest
 | |
|                                            QUERY PLAN                                            
 | |
| -------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" IS NULL))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL;    -- NullTest
 | |
|                                              QUERY PLAN                                              
 | |
| -----------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" IS NOT NULL))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE round(abs(c1), 0) = 1; -- FuncExpr
 | |
|                                                      QUERY PLAN                                                      
 | |
| ---------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    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))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = -c1;          -- OpExpr(l)
 | |
|                                              QUERY PLAN                                              
 | |
| -----------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = (- "C 1")))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE 1 = c1!;           -- OpExpr(r)
 | |
|                                                 QUERY PLAN                                                
 | |
| ----------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((1::numeric = ("C 1" !)))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE (c1 IS NOT NULL) IS DISTINCT FROM (c1 IS NOT NULL); -- DistinctExpr
 | |
|                                                                  QUERY PLAN                                                                 
 | |
| --------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    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)))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = ANY(ARRAY[c2, 1, c1 + 0]); -- ScalarArrayOpExpr
 | |
|                                                         QUERY PLAN                                                         
 | |
| ---------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    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)])))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c1 = (ARRAY[c1,c2,3])[1]; -- ArrayRef
 | |
|                                                       QUERY PLAN                                                      
 | |
| ----------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    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])))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c6 = E'foo''s\\bar';  -- check special chars
 | |
|                                                  QUERY PLAN                                                  
 | |
| -------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c6 = E'foo''s\\bar'::text))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 t1 WHERE c8 = 'foo';  -- can't be sent to remote
 | |
|                                QUERY PLAN                                
 | |
| -------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Filter: (t1.c8 = 'foo'::user_enum)
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
 | |
| (4 rows)
 | |
| 
 | |
| -- parameterized remote path for foreign table
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
|   SELECT * FROM "S 1"."T 1" a, ft2 b WHERE a."C 1" = 47 AND b.c1 = a.c2;
 | |
|                                                  QUERY PLAN                                                  
 | |
| -------------------------------------------------------------------------------------------------------------
 | |
|  Nested Loop
 | |
|    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
 | |
|    ->  Index Scan using t1_pkey on "S 1"."T 1" a
 | |
|          Output: a."C 1", a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8
 | |
|          Index Cond: (a."C 1" = 47)
 | |
|    ->  Foreign Scan on public.ft2 b
 | |
|          Output: b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8
 | |
|          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
 | |
| (8 rows)
 | |
| 
 | |
| SELECT * FROM ft2 a, ft2 b WHERE a.c1 = 47 AND b.c1 = a.c2;
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----+----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  47 |  7 | 00047 | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo |  7 |  7 | 00007 | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
| (1 row)
 | |
| 
 | |
| -- check both safe and unsafe join conditions
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
|   SELECT * FROM ft2 a, ft2 b
 | |
|   WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7);
 | |
|                                                  QUERY PLAN                                                  
 | |
| -------------------------------------------------------------------------------------------------------------
 | |
|  Nested Loop
 | |
|    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
 | |
|    ->  Foreign Scan on public.ft2 a
 | |
|          Output: a.c1, a.c2, a.c3, a.c4, a.c5, a.c6, a.c7, a.c8
 | |
|          Filter: (a.c8 = 'foo'::user_enum)
 | |
|          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((c2 = 6))
 | |
|    ->  Foreign Scan on public.ft2 b
 | |
|          Output: b.c1, b.c2, b.c3, b.c4, b.c5, b.c6, b.c7, b.c8
 | |
|          Filter: (upper((a.c7)::text) = (b.c7)::text)
 | |
|          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (($1::integer = "C 1"))
 | |
| (10 rows)
 | |
| 
 | |
| SELECT * FROM ft2 a, ft2 b
 | |
| WHERE a.c2 = 6 AND b.c1 = a.c1 AND a.c8 = 'foo' AND b.c7 = upper(a.c7);
 | |
|  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  | c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| -----+----+-------+------------------------------+--------------------------+----+------------+-----+-----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|    6 |  6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo |   6 |  6 | 00006 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|   16 |  6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo |  16 |  6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
|   26 |  6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo |  26 |  6 | 00026 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo
 | |
|   36 |  6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo |  36 |  6 | 00036 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo
 | |
|   46 |  6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo |  46 |  6 | 00046 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo
 | |
|   56 |  6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo |  56 |  6 | 00056 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo
 | |
|   66 |  6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo |  66 |  6 | 00066 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo
 | |
|   76 |  6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo |  76 |  6 | 00076 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo
 | |
|   86 |  6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo |  86 |  6 | 00086 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo
 | |
|   96 |  6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo |  96 |  6 | 00096 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  106 |  6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo | 106 |  6 | 00106 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  116 |  6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo | 116 |  6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
|  126 |  6 | 00126 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo | 126 |  6 | 00126 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo
 | |
|  136 |  6 | 00136 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo | 136 |  6 | 00136 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo
 | |
|  146 |  6 | 00146 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo | 146 |  6 | 00146 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo
 | |
|  156 |  6 | 00156 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo | 156 |  6 | 00156 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo
 | |
|  166 |  6 | 00166 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo | 166 |  6 | 00166 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo
 | |
|  176 |  6 | 00176 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo | 176 |  6 | 00176 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo
 | |
|  186 |  6 | 00186 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo | 186 |  6 | 00186 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo
 | |
|  196 |  6 | 00196 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo | 196 |  6 | 00196 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  206 |  6 | 00206 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo | 206 |  6 | 00206 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  216 |  6 | 00216 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo | 216 |  6 | 00216 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
|  226 |  6 | 00226 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo | 226 |  6 | 00226 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo
 | |
|  236 |  6 | 00236 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo | 236 |  6 | 00236 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo
 | |
|  246 |  6 | 00246 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo | 246 |  6 | 00246 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo
 | |
|  256 |  6 | 00256 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo | 256 |  6 | 00256 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo
 | |
|  266 |  6 | 00266 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo | 266 |  6 | 00266 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo
 | |
|  276 |  6 | 00276 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo | 276 |  6 | 00276 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo
 | |
|  286 |  6 | 00286 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo | 286 |  6 | 00286 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo
 | |
|  296 |  6 | 00296 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo | 296 |  6 | 00296 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  306 |  6 | 00306 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo | 306 |  6 | 00306 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  316 |  6 | 00316 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo | 316 |  6 | 00316 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
|  326 |  6 | 00326 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo | 326 |  6 | 00326 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo
 | |
|  336 |  6 | 00336 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo | 336 |  6 | 00336 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo
 | |
|  346 |  6 | 00346 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo | 346 |  6 | 00346 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo
 | |
|  356 |  6 | 00356 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo | 356 |  6 | 00356 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo
 | |
|  366 |  6 | 00366 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo | 366 |  6 | 00366 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo
 | |
|  376 |  6 | 00376 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo | 376 |  6 | 00376 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo
 | |
|  386 |  6 | 00386 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo | 386 |  6 | 00386 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo
 | |
|  396 |  6 | 00396 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo | 396 |  6 | 00396 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  406 |  6 | 00406 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo | 406 |  6 | 00406 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  416 |  6 | 00416 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo | 416 |  6 | 00416 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
|  426 |  6 | 00426 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo | 426 |  6 | 00426 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo
 | |
|  436 |  6 | 00436 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo | 436 |  6 | 00436 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo
 | |
|  446 |  6 | 00446 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo | 446 |  6 | 00446 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo
 | |
|  456 |  6 | 00456 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo | 456 |  6 | 00456 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo
 | |
|  466 |  6 | 00466 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo | 466 |  6 | 00466 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo
 | |
|  476 |  6 | 00476 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo | 476 |  6 | 00476 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo
 | |
|  486 |  6 | 00486 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo | 486 |  6 | 00486 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo
 | |
|  496 |  6 | 00496 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo | 496 |  6 | 00496 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  506 |  6 | 00506 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo | 506 |  6 | 00506 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  516 |  6 | 00516 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo | 516 |  6 | 00516 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
|  526 |  6 | 00526 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo | 526 |  6 | 00526 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo
 | |
|  536 |  6 | 00536 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo | 536 |  6 | 00536 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo
 | |
|  546 |  6 | 00546 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo | 546 |  6 | 00546 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo
 | |
|  556 |  6 | 00556 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo | 556 |  6 | 00556 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo
 | |
|  566 |  6 | 00566 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo | 566 |  6 | 00566 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo
 | |
|  576 |  6 | 00576 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo | 576 |  6 | 00576 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo
 | |
|  586 |  6 | 00586 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo | 586 |  6 | 00586 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo
 | |
|  596 |  6 | 00596 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo | 596 |  6 | 00596 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  606 |  6 | 00606 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo | 606 |  6 | 00606 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  616 |  6 | 00616 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo | 616 |  6 | 00616 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
|  626 |  6 | 00626 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo | 626 |  6 | 00626 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo
 | |
|  636 |  6 | 00636 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo | 636 |  6 | 00636 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo
 | |
|  646 |  6 | 00646 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo | 646 |  6 | 00646 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo
 | |
|  656 |  6 | 00656 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo | 656 |  6 | 00656 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo
 | |
|  666 |  6 | 00666 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo | 666 |  6 | 00666 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo
 | |
|  676 |  6 | 00676 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo | 676 |  6 | 00676 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo
 | |
|  686 |  6 | 00686 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo | 686 |  6 | 00686 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo
 | |
|  696 |  6 | 00696 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo | 696 |  6 | 00696 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  706 |  6 | 00706 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo | 706 |  6 | 00706 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  716 |  6 | 00716 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo | 716 |  6 | 00716 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
|  726 |  6 | 00726 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo | 726 |  6 | 00726 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo
 | |
|  736 |  6 | 00736 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo | 736 |  6 | 00736 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo
 | |
|  746 |  6 | 00746 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo | 746 |  6 | 00746 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo
 | |
|  756 |  6 | 00756 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo | 756 |  6 | 00756 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo
 | |
|  766 |  6 | 00766 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo | 766 |  6 | 00766 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo
 | |
|  776 |  6 | 00776 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo | 776 |  6 | 00776 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo
 | |
|  786 |  6 | 00786 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo | 786 |  6 | 00786 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo
 | |
|  796 |  6 | 00796 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo | 796 |  6 | 00796 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  806 |  6 | 00806 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo | 806 |  6 | 00806 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  816 |  6 | 00816 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo | 816 |  6 | 00816 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
|  826 |  6 | 00826 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo | 826 |  6 | 00826 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo
 | |
|  836 |  6 | 00836 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo | 836 |  6 | 00836 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo
 | |
|  846 |  6 | 00846 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo | 846 |  6 | 00846 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo
 | |
|  856 |  6 | 00856 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo | 856 |  6 | 00856 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo
 | |
|  866 |  6 | 00866 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo | 866 |  6 | 00866 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo
 | |
|  876 |  6 | 00876 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo | 876 |  6 | 00876 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo
 | |
|  886 |  6 | 00886 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo | 886 |  6 | 00886 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo
 | |
|  896 |  6 | 00896 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo | 896 |  6 | 00896 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  906 |  6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo | 906 |  6 | 00906 | Wed Jan 07 00:00:00 1970 PST | Wed Jan 07 00:00:00 1970 | 6  | 6          | foo
 | |
|  916 |  6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo | 916 |  6 | 00916 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
|  926 |  6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo | 926 |  6 | 00926 | Tue Jan 27 00:00:00 1970 PST | Tue Jan 27 00:00:00 1970 | 6  | 6          | foo
 | |
|  936 |  6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo | 936 |  6 | 00936 | Fri Feb 06 00:00:00 1970 PST | Fri Feb 06 00:00:00 1970 | 6  | 6          | foo
 | |
|  946 |  6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo | 946 |  6 | 00946 | Mon Feb 16 00:00:00 1970 PST | Mon Feb 16 00:00:00 1970 | 6  | 6          | foo
 | |
|  956 |  6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo | 956 |  6 | 00956 | Thu Feb 26 00:00:00 1970 PST | Thu Feb 26 00:00:00 1970 | 6  | 6          | foo
 | |
|  966 |  6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo | 966 |  6 | 00966 | Sun Mar 08 00:00:00 1970 PST | Sun Mar 08 00:00:00 1970 | 6  | 6          | foo
 | |
|  976 |  6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo | 976 |  6 | 00976 | Wed Mar 18 00:00:00 1970 PST | Wed Mar 18 00:00:00 1970 | 6  | 6          | foo
 | |
|  986 |  6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo | 986 |  6 | 00986 | Sat Mar 28 00:00:00 1970 PST | Sat Mar 28 00:00:00 1970 | 6  | 6          | foo
 | |
|  996 |  6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo | 996 |  6 | 00996 | Tue Apr 07 00:00:00 1970 PST | Tue Apr 07 00:00:00 1970 | 6  | 6          | foo
 | |
| (100 rows)
 | |
| 
 | |
| -- bug before 9.3.5 due to sloppy handling of remote-estimate parameters
 | |
| SELECT * FROM ft1 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft2 WHERE c1 < 5));
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
|   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
 | |
|   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
 | |
|   4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
 | |
| (4 rows)
 | |
| 
 | |
| SELECT * FROM ft2 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft1 WHERE c1 < 5));
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
|   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
 | |
|   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
 | |
|   4 |  4 | 00004 | Mon Jan 05 00:00:00 1970 PST | Mon Jan 05 00:00:00 1970 | 4  | 4          | foo
 | |
| (4 rows)
 | |
| 
 | |
| -- we should not push order by clause with volatile expressions or unsafe
 | |
| -- collations
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| 	SELECT * FROM ft2 ORDER BY ft2.c1, random();
 | |
|                                   QUERY PLAN                                   
 | |
| -------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8, (random())
 | |
|    Sort Key: ft2.c1, (random())
 | |
|    ->  Foreign Scan on public.ft2
 | |
|          Output: c1, c2, c3, c4, c5, c6, c7, c8, random()
 | |
|          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
 | |
| (6 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| 	SELECT * FROM ft2 ORDER BY ft2.c1, ft2.c3 collate "C";
 | |
|                                   QUERY PLAN                                   
 | |
| -------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8, ((c3)::text)
 | |
|    Sort Key: ft2.c1, ft2.c3 COLLATE "C"
 | |
|    ->  Foreign Scan on public.ft2
 | |
|          Output: c1, c2, c3, c4, c5, c6, c7, c8, c3
 | |
|          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
 | |
| (6 rows)
 | |
| 
 | |
| -- user-defined operator/function
 | |
| CREATE FUNCTION postgres_fdw_abs(int) RETURNS int AS $$
 | |
| BEGIN
 | |
| RETURN abs($1);
 | |
| END
 | |
| $$ LANGUAGE plpgsql IMMUTABLE;
 | |
| CREATE OPERATOR === (
 | |
|     LEFTARG = int,
 | |
|     RIGHTARG = int,
 | |
|     PROCEDURE = int4eq,
 | |
|     COMMUTATOR = ===
 | |
| );
 | |
| -- built-in operators and functions can be shipped for remote execution
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
|   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
 | |
|                                 QUERY PLAN                                 
 | |
| ---------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: (count(c3))
 | |
|    Relations: Aggregate on (public.ft1 t1)
 | |
|    Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" = abs(c2)))
 | |
| (4 rows)
 | |
| 
 | |
| SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = abs(t1.c2);
 | |
|  count 
 | |
| -------
 | |
|      9
 | |
| (1 row)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
|   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
 | |
|                               QUERY PLAN                              
 | |
| ----------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: (count(c3))
 | |
|    Relations: Aggregate on (public.ft1 t1)
 | |
|    Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" = c2))
 | |
| (4 rows)
 | |
| 
 | |
| SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = t1.c2;
 | |
|  count 
 | |
| -------
 | |
|      9
 | |
| (1 row)
 | |
| 
 | |
| -- by default, user-defined ones cannot
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
|   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
 | |
|                         QUERY PLAN                         
 | |
| -----------------------------------------------------------
 | |
|  Aggregate
 | |
|    Output: count(c3)
 | |
|    ->  Foreign Scan on public.ft1 t1
 | |
|          Output: c3
 | |
|          Filter: (t1.c1 = postgres_fdw_abs(t1.c2))
 | |
|          Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
 | |
| (6 rows)
 | |
| 
 | |
| SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
 | |
|  count 
 | |
| -------
 | |
|      9
 | |
| (1 row)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
|   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
 | |
|                         QUERY PLAN                         
 | |
| -----------------------------------------------------------
 | |
|  Aggregate
 | |
|    Output: count(c3)
 | |
|    ->  Foreign Scan on public.ft1 t1
 | |
|          Output: c3
 | |
|          Filter: (t1.c1 === t1.c2)
 | |
|          Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
 | |
| (6 rows)
 | |
| 
 | |
| SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
 | |
|  count 
 | |
| -------
 | |
|      9
 | |
| (1 row)
 | |
| 
 | |
| -- but let's put them in an extension ...
 | |
| ALTER EXTENSION postgres_fdw ADD FUNCTION postgres_fdw_abs(int);
 | |
| ALTER EXTENSION postgres_fdw ADD OPERATOR === (int, int);
 | |
| ALTER SERVER loopback OPTIONS (ADD extensions 'postgres_fdw');
 | |
| -- ... now they can be shipped
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
|   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
 | |
|                                           QUERY PLAN                                           
 | |
| -----------------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: (count(c3))
 | |
|    Relations: Aggregate on (public.ft1 t1)
 | |
|    Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" = public.postgres_fdw_abs(c2)))
 | |
| (4 rows)
 | |
| 
 | |
| SELECT count(c3) FROM ft1 t1 WHERE t1.c1 = postgres_fdw_abs(t1.c2);
 | |
|  count 
 | |
| -------
 | |
|      9
 | |
| (1 row)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
|   SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
 | |
|                                        QUERY PLAN                                        
 | |
| -----------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: (count(c3))
 | |
|    Relations: Aggregate on (public.ft1 t1)
 | |
|    Remote SQL: SELECT count(c3) FROM "S 1"."T 1" WHERE (("C 1" OPERATOR(public.===) c2))
 | |
| (4 rows)
 | |
| 
 | |
| SELECT count(c3) FROM ft1 t1 WHERE t1.c1 === t1.c2;
 | |
|  count 
 | |
| -------
 | |
|      9
 | |
| (1 row)
 | |
| 
 | |
| -- ===================================================================
 | |
| -- JOIN queries
 | |
| -- ===================================================================
 | |
| -- Analyze ft4 and ft5 so that we have better statistics. These tables do not
 | |
| -- have use_remote_estimate set.
 | |
| ANALYZE ft4;
 | |
| ANALYZE ft5;
 | |
| -- join two tables
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
 | |
|                                                                                         QUERY PLAN                                                                                        
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1, t1.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c1, t1.c3
 | |
|          Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|          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
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
 | |
|  c1  | c1  
 | |
| -----+-----
 | |
|  101 | 101
 | |
|  102 | 102
 | |
|  103 | 103
 | |
|  104 | 104
 | |
|  105 | 105
 | |
|  106 | 106
 | |
|  107 | 107
 | |
|  108 | 108
 | |
|  109 | 109
 | |
|  110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| -- join three tables
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10;
 | |
|                                                                                             QUERY PLAN                                                                                             
 | |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c2, t3.c3, t1.c3
 | |
|    ->  Sort
 | |
|          Output: t1.c1, t2.c2, t3.c3, t1.c3
 | |
|          Sort Key: t1.c3, t1.c1
 | |
|          ->  Foreign Scan
 | |
|                Output: t1.c1, t2.c2, t3.c3, t1.c3
 | |
|                Relations: ((public.ft1 t1) INNER JOIN (public.ft2 t2)) INNER JOIN (public.ft4 t3)
 | |
|                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))))
 | |
| (9 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) JOIN ft4 t3 ON (t3.c1 = t1.c1) ORDER BY t1.c3, t1.c1 OFFSET 10 LIMIT 10;
 | |
|  c1 | c2 |   c3   
 | |
| ----+----+--------
 | |
|  22 |  2 | AAA022
 | |
|  24 |  4 | AAA024
 | |
|  26 |  6 | AAA026
 | |
|  28 |  8 | AAA028
 | |
|  30 |  0 | AAA030
 | |
|  32 |  2 | AAA032
 | |
|  34 |  4 | AAA034
 | |
|  36 |  6 | AAA036
 | |
|  38 |  8 | AAA038
 | |
|  40 |  0 | AAA040
 | |
| (10 rows)
 | |
| 
 | |
| -- left outer join
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
 | |
|                                                                             QUERY PLAN                                                                             
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c1
 | |
|          Relations: (public.ft4 t1) LEFT JOIN (public.ft5 t2)
 | |
|          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
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
 | |
|  c1 | c1 
 | |
| ----+----
 | |
|  22 |   
 | |
|  24 | 24
 | |
|  26 |   
 | |
|  28 |   
 | |
|  30 | 30
 | |
|  32 |   
 | |
|  34 |   
 | |
|  36 | 36
 | |
|  38 |   
 | |
|  40 |   
 | |
| (10 rows)
 | |
| 
 | |
| -- left outer join three tables
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|                                                                                      QUERY PLAN                                                                                     
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c2, t3.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c2, t3.c3
 | |
|          Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
 | |
|          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))))
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|  c1 | c2 |   c3   
 | |
| ----+----+--------
 | |
|  11 |  1 | 
 | |
|  12 |  2 | AAA012
 | |
|  13 |  3 | 
 | |
|  14 |  4 | AAA014
 | |
|  15 |  5 | 
 | |
|  16 |  6 | AAA016
 | |
|  17 |  7 | 
 | |
|  18 |  8 | AAA018
 | |
|  19 |  9 | 
 | |
|  20 |  0 | AAA020
 | |
| (10 rows)
 | |
| 
 | |
| -- left outer join + placement of clauses.
 | |
| -- clauses within the nullable side are not pulled up, but top level clause on
 | |
| -- non-nullable side is pushed into non-nullable side
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10;
 | |
|                                                                           QUERY PLAN                                                                           
 | |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: t1.c1, t1.c2, ft5.c1, ft5.c2
 | |
|    Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
 | |
|    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))
 | |
| (4 rows)
 | |
| 
 | |
| SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1) WHERE t1.c1 < 10;
 | |
|  c1 | c2 | c1 | c2 
 | |
| ----+----+----+----
 | |
|   2 |  3 |    |   
 | |
|   4 |  5 |    |   
 | |
|   6 |  7 |  6 |  7
 | |
|   8 |  9 |    |   
 | |
| (4 rows)
 | |
| 
 | |
| -- clauses within the nullable side are not pulled up, but the top level clause
 | |
| -- on nullable side is not pushed down into nullable side
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1)
 | |
| 			WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
 | |
|                                                                                               QUERY PLAN                                                                                               
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: t1.c1, t1.c2, ft5.c1, ft5.c2
 | |
|    Relations: (public.ft4 t1) LEFT JOIN (public.ft5)
 | |
|    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))
 | |
| (4 rows)
 | |
| 
 | |
| SELECT t1.c1, t1.c2, t2.c1, t2.c2 FROM ft4 t1 LEFT JOIN (SELECT * FROM ft5 WHERE c1 < 10) t2 ON (t1.c1 = t2.c1)
 | |
| 			WHERE (t2.c1 < 10 OR t2.c1 IS NULL) AND t1.c1 < 10;
 | |
|  c1 | c2 | c1 | c2 
 | |
| ----+----+----+----
 | |
|   2 |  3 |    |   
 | |
|   4 |  5 |    |   
 | |
|   6 |  7 |  6 |  7
 | |
|   8 |  9 |    |   
 | |
| (4 rows)
 | |
| 
 | |
| -- right outer join
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10;
 | |
|                                                                             QUERY PLAN                                                                             
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c1
 | |
|          Relations: (public.ft4 t2) LEFT JOIN (public.ft5 t1)
 | |
|          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
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft5 t1 RIGHT JOIN ft4 t2 ON (t1.c1 = t2.c1) ORDER BY t2.c1, t1.c1 OFFSET 10 LIMIT 10;
 | |
|  c1 | c1 
 | |
| ----+----
 | |
|     | 22
 | |
|  24 | 24
 | |
|     | 26
 | |
|     | 28
 | |
|  30 | 30
 | |
|     | 32
 | |
|     | 34
 | |
|  36 | 36
 | |
|     | 38
 | |
|     | 40
 | |
| (10 rows)
 | |
| 
 | |
| -- right outer join three tables
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|                                                                                      QUERY PLAN                                                                                     
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c2, t3.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c2, t3.c3
 | |
|          Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
 | |
|          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"))))
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|  c1 | c2 |   c3   
 | |
| ----+----+--------
 | |
|  22 |  2 | AAA022
 | |
|  24 |  4 | AAA024
 | |
|  26 |  6 | AAA026
 | |
|  28 |  8 | AAA028
 | |
|  30 |  0 | AAA030
 | |
|  32 |  2 | AAA032
 | |
|  34 |  4 | AAA034
 | |
|  36 |  6 | AAA036
 | |
|  38 |  8 | AAA038
 | |
|  40 |  0 | AAA040
 | |
| (10 rows)
 | |
| 
 | |
| -- full outer join
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10;
 | |
|                                                                             QUERY PLAN                                                                             
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c1
 | |
|          Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
 | |
|          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
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 45 LIMIT 10;
 | |
|  c1  | c1 
 | |
| -----+----
 | |
|   92 |   
 | |
|   94 |   
 | |
|   96 | 96
 | |
|   98 |   
 | |
|  100 |   
 | |
|      |  3
 | |
|      |  9
 | |
|      | 15
 | |
|      | 21
 | |
|      | 27
 | |
| (10 rows)
 | |
| 
 | |
| -- full outer join with restrictions on the joining relations
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1;
 | |
|                                            QUERY PLAN                                           
 | |
| ------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: ft4.c1, ft5.c1
 | |
|    Sort Key: ft4.c1, ft5.c1
 | |
|    ->  Hash Full Join
 | |
|          Output: ft4.c1, ft5.c1
 | |
|          Hash Cond: (ft4.c1 = ft5.c1)
 | |
|          ->  Foreign Scan on public.ft4
 | |
|                Output: ft4.c1, ft4.c2, ft4.c3
 | |
|                Remote SQL: SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 50)) AND ((c1 <= 60))
 | |
|          ->  Hash
 | |
|                Output: ft5.c1
 | |
|                ->  Foreign Scan on public.ft5
 | |
|                      Output: ft5.c1
 | |
|                      Remote SQL: SELECT c1 FROM "S 1"."T 4" WHERE ((c1 >= 50)) AND ((c1 <= 60))
 | |
| (14 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM (SELECT c1 FROM ft4 WHERE c1 between 50 and 60) t1 FULL JOIN (SELECT c1 FROM ft5 WHERE c1 between 50 and 60) t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1;
 | |
|  c1 | c1 
 | |
| ----+----
 | |
|  50 |   
 | |
|  52 |   
 | |
|  54 | 54
 | |
|  56 |   
 | |
|  58 |   
 | |
|  60 | 60
 | |
|     | 51
 | |
|     | 57
 | |
| (8 rows)
 | |
| 
 | |
| -- full outer join + inner join
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10;
 | |
|                                                                                                                                            QUERY PLAN                                                                                                                                            
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1, t3.c1
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c1, t3.c1
 | |
|          Relations: ((public.ft4 t1) INNER JOIN (public.ft5 t2)) FULL JOIN (public.ft4 t3)
 | |
|          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
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1, t3.c1 FROM ft4 t1 INNER JOIN ft5 t2 ON (t1.c1 = t2.c1 + 1 and t1.c1 between 50 and 60) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) ORDER BY t1.c1, t2.c1, t3.c1 LIMIT 10;
 | |
|  c1 | c1 | c1 
 | |
| ----+----+----
 | |
|  52 | 51 |   
 | |
|  58 | 57 |   
 | |
|     |    |  2
 | |
|     |    |  4
 | |
|     |    |  6
 | |
|     |    |  8
 | |
|     |    | 10
 | |
|     |    | 12
 | |
|     |    | 14
 | |
|     |    | 16
 | |
| (10 rows)
 | |
| 
 | |
| -- full outer join three tables
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|                                                                                      QUERY PLAN                                                                                     
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c2, t3.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c2, t3.c3
 | |
|          Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
 | |
|          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))))
 | |
| (6 rows)
 | |
| 
 | |
| 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;
 | |
|  c1 | c2 |   c3   
 | |
| ----+----+--------
 | |
|  11 |  1 | 
 | |
|  12 |  2 | AAA012
 | |
|  13 |  3 | 
 | |
|  14 |  4 | AAA014
 | |
|  15 |  5 | 
 | |
|  16 |  6 | AAA016
 | |
|  17 |  7 | 
 | |
|  18 |  8 | AAA018
 | |
|  19 |  9 | 
 | |
|  20 |  0 | AAA020
 | |
| (10 rows)
 | |
| 
 | |
| -- full outer join + right outer join
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|                                                                                      QUERY PLAN                                                                                     
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c2, t3.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c2, t3.c3
 | |
|          Relations: ((public.ft4 t3) LEFT JOIN (public.ft2 t2)) LEFT JOIN (public.ft2 t1)
 | |
|          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"))))
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|  c1 | c2 |   c3   
 | |
| ----+----+--------
 | |
|  22 |  2 | AAA022
 | |
|  24 |  4 | AAA024
 | |
|  26 |  6 | AAA026
 | |
|  28 |  8 | AAA028
 | |
|  30 |  0 | AAA030
 | |
|  32 |  2 | AAA032
 | |
|  34 |  4 | AAA034
 | |
|  36 |  6 | AAA036
 | |
|  38 |  8 | AAA038
 | |
|  40 |  0 | AAA040
 | |
| (10 rows)
 | |
| 
 | |
| -- right outer join + full outer join
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|                                                                                      QUERY PLAN                                                                                     
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c2, t3.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c2, t3.c3
 | |
|          Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) FULL JOIN (public.ft4 t3)
 | |
|          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))))
 | |
| (6 rows)
 | |
| 
 | |
| 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;
 | |
|  c1 | c2 |   c3   
 | |
| ----+----+--------
 | |
|  11 |  1 | 
 | |
|  12 |  2 | AAA012
 | |
|  13 |  3 | 
 | |
|  14 |  4 | AAA014
 | |
|  15 |  5 | 
 | |
|  16 |  6 | AAA016
 | |
|  17 |  7 | 
 | |
|  18 |  8 | AAA018
 | |
|  19 |  9 | 
 | |
|  20 |  0 | AAA020
 | |
| (10 rows)
 | |
| 
 | |
| -- full outer join + left outer join
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 FULL JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|                                                                                      QUERY PLAN                                                                                     
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c2, t3.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c2, t3.c3
 | |
|          Relations: ((public.ft2 t1) FULL JOIN (public.ft2 t2)) LEFT JOIN (public.ft4 t3)
 | |
|          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))))
 | |
| (6 rows)
 | |
| 
 | |
| 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;
 | |
|  c1 | c2 |   c3   
 | |
| ----+----+--------
 | |
|  11 |  1 | 
 | |
|  12 |  2 | AAA012
 | |
|  13 |  3 | 
 | |
|  14 |  4 | AAA014
 | |
|  15 |  5 | 
 | |
|  16 |  6 | AAA016
 | |
|  17 |  7 | 
 | |
|  18 |  8 | AAA018
 | |
|  19 |  9 | 
 | |
|  20 |  0 | AAA020
 | |
| (10 rows)
 | |
| 
 | |
| -- left outer join + full outer join
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) FULL JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|                                                                                      QUERY PLAN                                                                                     
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c2, t3.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c2, t3.c3
 | |
|          Relations: ((public.ft2 t1) LEFT JOIN (public.ft2 t2)) FULL JOIN (public.ft4 t3)
 | |
|          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))))
 | |
| (6 rows)
 | |
| 
 | |
| 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;
 | |
|  c1 | c2 |   c3   
 | |
| ----+----+--------
 | |
|  11 |  1 | 
 | |
|  12 |  2 | AAA012
 | |
|  13 |  3 | 
 | |
|  14 |  4 | AAA014
 | |
|  15 |  5 | 
 | |
|  16 |  6 | AAA016
 | |
|  17 |  7 | 
 | |
|  18 |  8 | AAA018
 | |
|  19 |  9 | 
 | |
|  20 |  0 | AAA020
 | |
| (10 rows)
 | |
| 
 | |
| -- right outer join + left outer join
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|                                                                                      QUERY PLAN                                                                                     
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c2, t3.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c2, t3.c3
 | |
|          Relations: ((public.ft2 t2) LEFT JOIN (public.ft2 t1)) LEFT JOIN (public.ft4 t3)
 | |
|          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))))
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 RIGHT JOIN ft2 t2 ON (t1.c1 = t2.c1) LEFT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|  c1 | c2 |   c3   
 | |
| ----+----+--------
 | |
|  11 |  1 | 
 | |
|  12 |  2 | AAA012
 | |
|  13 |  3 | 
 | |
|  14 |  4 | AAA014
 | |
|  15 |  5 | 
 | |
|  16 |  6 | AAA016
 | |
|  17 |  7 | 
 | |
|  18 |  8 | AAA018
 | |
|  19 |  9 | 
 | |
|  20 |  0 | AAA020
 | |
| (10 rows)
 | |
| 
 | |
| -- left outer join + right outer join
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2, t3.c3 FROM ft2 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) RIGHT JOIN ft4 t3 ON (t2.c1 = t3.c1) OFFSET 10 LIMIT 10;
 | |
|                                                                                      QUERY PLAN                                                                                      
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c2, t3.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c2, t3.c3
 | |
|          Relations: (public.ft4 t3) LEFT JOIN ((public.ft2 t1) INNER JOIN (public.ft2 t2))
 | |
|          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))))
 | |
| (6 rows)
 | |
| 
 | |
| 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;
 | |
|  c1 | c2 |   c3   
 | |
| ----+----+--------
 | |
|  22 |  2 | AAA022
 | |
|  24 |  4 | AAA024
 | |
|  26 |  6 | AAA026
 | |
|  28 |  8 | AAA028
 | |
|  30 |  0 | AAA030
 | |
|  32 |  2 | AAA032
 | |
|  34 |  4 | AAA034
 | |
|  36 |  6 | AAA036
 | |
|  38 |  8 | AAA038
 | |
|  40 |  0 | AAA040
 | |
| (10 rows)
 | |
| 
 | |
| -- full outer join + WHERE clause, only matched rows
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
 | |
|                                                                             QUERY PLAN                                                                            
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1
 | |
|    ->  Sort
 | |
|          Output: t1.c1, t2.c1
 | |
|          Sort Key: t1.c1, t2.c1
 | |
|          ->  Foreign Scan
 | |
|                Output: t1.c1, t2.c1
 | |
|                Relations: (public.ft4 t1) FULL JOIN (public.ft5 t2)
 | |
|                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)))
 | |
| (9 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft4 t1 FULL JOIN ft5 t2 ON (t1.c1 = t2.c1) WHERE (t1.c1 = t2.c1 OR t1.c1 IS NULL) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
 | |
|  c1 | c1 
 | |
| ----+----
 | |
|  66 | 66
 | |
|  72 | 72
 | |
|  78 | 78
 | |
|  84 | 84
 | |
|  90 | 90
 | |
|  96 | 96
 | |
|     |  3
 | |
|     |  9
 | |
|     | 15
 | |
|     | 21
 | |
| (10 rows)
 | |
| 
 | |
| -- join two tables with FOR UPDATE clause
 | |
| -- tests whole-row reference for row marks
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1;
 | |
|                                                                                                                                                                                                                QUERY PLAN                                                                                                                                                                                                                
 | |
| -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|    ->  LockRows
 | |
|          Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|          ->  Foreign Scan
 | |
|                Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|                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
 | |
|                ->  Merge Join
 | |
|                      Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
 | |
|                      Merge Cond: (t1.c1 = t2.c1)
 | |
|                      ->  Sort
 | |
|                            Output: t1.c1, t1.c3, t1.*
 | |
|                            Sort Key: t1.c1
 | |
|                            ->  Foreign Scan on public.ft1 t1
 | |
|                                  Output: t1.c1, t1.c3, t1.*
 | |
|                                  Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
 | |
|                      ->  Sort
 | |
|                            Output: t2.c1, t2.*
 | |
|                            Sort Key: t2.c1
 | |
|                            ->  Foreign Scan on public.ft2 t2
 | |
|                                  Output: t2.c1, t2.*
 | |
|                                  Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
 | |
| (23 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE OF t1;
 | |
|  c1  | c1  
 | |
| -----+-----
 | |
|  101 | 101
 | |
|  102 | 102
 | |
|  103 | 103
 | |
|  104 | 104
 | |
|  105 | 105
 | |
|  106 | 106
 | |
|  107 | 107
 | |
|  108 | 108
 | |
|  109 | 109
 | |
|  110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE;
 | |
|                                                                                                                                                                                                                         QUERY PLAN                                                                                                                                                                                                                        
 | |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|    ->  LockRows
 | |
|          Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|          ->  Foreign Scan
 | |
|                Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|                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
 | |
|                ->  Merge Join
 | |
|                      Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
 | |
|                      Merge Cond: (t1.c1 = t2.c1)
 | |
|                      ->  Sort
 | |
|                            Output: t1.c1, t1.c3, t1.*
 | |
|                            Sort Key: t1.c1
 | |
|                            ->  Foreign Scan on public.ft1 t1
 | |
|                                  Output: t1.c1, t1.c3, t1.*
 | |
|                                  Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
 | |
|                      ->  Sort
 | |
|                            Output: t2.c1, t2.*
 | |
|                            Sort Key: t2.c1
 | |
|                            ->  Foreign Scan on public.ft2 t2
 | |
|                                  Output: t2.c1, t2.*
 | |
|                                  Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR UPDATE
 | |
| (23 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR UPDATE;
 | |
|  c1  | c1  
 | |
| -----+-----
 | |
|  101 | 101
 | |
|  102 | 102
 | |
|  103 | 103
 | |
|  104 | 104
 | |
|  105 | 105
 | |
|  106 | 106
 | |
|  107 | 107
 | |
|  108 | 108
 | |
|  109 | 109
 | |
|  110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| -- join two tables with FOR SHARE clause
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1;
 | |
|                                                                                                                                                                                                                QUERY PLAN                                                                                                                                                                                                               
 | |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|    ->  LockRows
 | |
|          Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|          ->  Foreign Scan
 | |
|                Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|                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
 | |
|                ->  Merge Join
 | |
|                      Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
 | |
|                      Merge Cond: (t1.c1 = t2.c1)
 | |
|                      ->  Sort
 | |
|                            Output: t1.c1, t1.c3, t1.*
 | |
|                            Sort Key: t1.c1
 | |
|                            ->  Foreign Scan on public.ft1 t1
 | |
|                                  Output: t1.c1, t1.c3, t1.*
 | |
|                                  Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
 | |
|                      ->  Sort
 | |
|                            Output: t2.c1, t2.*
 | |
|                            Sort Key: t2.c1
 | |
|                            ->  Foreign Scan on public.ft2 t2
 | |
|                                  Output: t2.c1, t2.*
 | |
|                                  Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
 | |
| (23 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE OF t1;
 | |
|  c1  | c1  
 | |
| -----+-----
 | |
|  101 | 101
 | |
|  102 | 102
 | |
|  103 | 103
 | |
|  104 | 104
 | |
|  105 | 105
 | |
|  106 | 106
 | |
|  107 | 107
 | |
|  108 | 108
 | |
|  109 | 109
 | |
|  110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE;
 | |
|                                                                                                                                                                                                                        QUERY PLAN                                                                                                                                                                                                                       
 | |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|    ->  LockRows
 | |
|          Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|          ->  Foreign Scan
 | |
|                Output: t1.c1, t2.c1, t1.c3, t1.*, t2.*
 | |
|                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|                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
 | |
|                ->  Merge Join
 | |
|                      Output: t1.c1, t1.c3, t1.*, t2.c1, t2.*
 | |
|                      Merge Cond: (t1.c1 = t2.c1)
 | |
|                      ->  Sort
 | |
|                            Output: t1.c1, t1.c3, t1.*
 | |
|                            Sort Key: t1.c1
 | |
|                            ->  Foreign Scan on public.ft1 t1
 | |
|                                  Output: t1.c1, t1.c3, t1.*
 | |
|                                  Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
 | |
|                      ->  Sort
 | |
|                            Output: t2.c1, t2.*
 | |
|                            Sort Key: t2.c1
 | |
|                            ->  Foreign Scan on public.ft2 t2
 | |
|                                  Output: t2.c1, t2.*
 | |
|                                  Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" FOR SHARE
 | |
| (23 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10 FOR SHARE;
 | |
|  c1  | c1  
 | |
| -----+-----
 | |
|  101 | 101
 | |
|  102 | 102
 | |
|  103 | 103
 | |
|  104 | 104
 | |
|  105 | 105
 | |
|  106 | 106
 | |
|  107 | 107
 | |
|  108 | 108
 | |
|  109 | 109
 | |
|  110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| -- join in CTE
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| 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;
 | |
|                                                              QUERY PLAN                                                              
 | |
| -------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t.c1_1, t.c2_1, t.c1_3
 | |
|    CTE t
 | |
|      ->  Foreign Scan
 | |
|            Output: t1.c1, t1.c3, t2.c1
 | |
|            Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|            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"))))
 | |
|    ->  Sort
 | |
|          Output: t.c1_1, t.c2_1, t.c1_3
 | |
|          Sort Key: t.c1_3, t.c1_1
 | |
|          ->  CTE Scan on t
 | |
|                Output: t.c1_1, t.c2_1, t.c1_3
 | |
| (12 rows)
 | |
| 
 | |
| 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;
 | |
|  c1_1 | c2_1 
 | |
| ------+------
 | |
|   101 |  101
 | |
|   102 |  102
 | |
|   103 |  103
 | |
|   104 |  104
 | |
|   105 |  105
 | |
|   106 |  106
 | |
|   107 |  107
 | |
|   108 |  108
 | |
|   109 |  109
 | |
|   110 |  110
 | |
| (10 rows)
 | |
| 
 | |
| -- ctid with whole-row reference
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.ctid, t1, t2, t1.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
 | |
|                                                                                                                                                                                                    QUERY PLAN                                                                                                                                                                                                    
 | |
| -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.ctid, t1.*, t2.*, t1.c1, t1.c3
 | |
|          Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|          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
 | |
| (6 rows)
 | |
| 
 | |
| -- SEMI JOIN, not pushed down
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1
 | |
|    ->  Merge Semi Join
 | |
|          Output: t1.c1
 | |
|          Merge Cond: (t1.c1 = t2.c1)
 | |
|          ->  Foreign Scan on public.ft1 t1
 | |
|                Output: t1.c1
 | |
|                Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
 | |
|          ->  Materialize
 | |
|                Output: t2.c1
 | |
|                ->  Foreign Scan on public.ft2 t2
 | |
|                      Output: t2.c1
 | |
|                      Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
 | |
| (13 rows)
 | |
| 
 | |
| SELECT t1.c1 FROM ft1 t1 WHERE EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c1) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
 | |
|  c1  
 | |
| -----
 | |
|  101
 | |
|  102
 | |
|  103
 | |
|  104
 | |
|  105
 | |
|  106
 | |
|  107
 | |
|  108
 | |
|  109
 | |
|  110
 | |
| (10 rows)
 | |
| 
 | |
| -- ANTI JOIN, not pushed down
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
 | |
|                                       QUERY PLAN                                       
 | |
| ---------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1
 | |
|    ->  Merge Anti Join
 | |
|          Output: t1.c1
 | |
|          Merge Cond: (t1.c1 = t2.c2)
 | |
|          ->  Foreign Scan on public.ft1 t1
 | |
|                Output: t1.c1
 | |
|                Remote SQL: SELECT "C 1" FROM "S 1"."T 1" ORDER BY "C 1" ASC NULLS LAST
 | |
|          ->  Materialize
 | |
|                Output: t2.c2
 | |
|                ->  Foreign Scan on public.ft2 t2
 | |
|                      Output: t2.c2
 | |
|                      Remote SQL: SELECT c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
 | |
| (13 rows)
 | |
| 
 | |
| SELECT t1.c1 FROM ft1 t1 WHERE NOT EXISTS (SELECT 1 FROM ft2 t2 WHERE t1.c1 = t2.c2) ORDER BY t1.c1 OFFSET 100 LIMIT 10;
 | |
|  c1  
 | |
| -----
 | |
|  110
 | |
|  111
 | |
|  112
 | |
|  113
 | |
|  114
 | |
|  115
 | |
|  116
 | |
|  117
 | |
|  118
 | |
|  119
 | |
| (10 rows)
 | |
| 
 | |
| -- CROSS JOIN, not pushed down
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
 | |
|                              QUERY PLAN                              
 | |
| ---------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1
 | |
|    ->  Sort
 | |
|          Output: t1.c1, t2.c1
 | |
|          Sort Key: t1.c1, t2.c1
 | |
|          ->  Nested Loop
 | |
|                Output: t1.c1, t2.c1
 | |
|                ->  Foreign Scan on public.ft1 t1
 | |
|                      Output: t1.c1
 | |
|                      Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
 | |
|                ->  Materialize
 | |
|                      Output: t2.c1
 | |
|                      ->  Foreign Scan on public.ft2 t2
 | |
|                            Output: t2.c1
 | |
|                            Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
 | |
| (15 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
 | |
|  c1 | c1  
 | |
| ----+-----
 | |
|   1 | 101
 | |
|   1 | 102
 | |
|   1 | 103
 | |
|   1 | 104
 | |
|   1 | 105
 | |
|   1 | 106
 | |
|   1 | 107
 | |
|   1 | 108
 | |
|   1 | 109
 | |
|   1 | 110
 | |
| (10 rows)
 | |
| 
 | |
| -- different server, not pushed down. No result expected.
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
 | |
|                                       QUERY PLAN                                       
 | |
| ---------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1
 | |
|    ->  Merge Join
 | |
|          Output: t1.c1, t2.c1
 | |
|          Merge Cond: (t2.c1 = t1.c1)
 | |
|          ->  Foreign Scan on public.ft6 t2
 | |
|                Output: t2.c1, t2.c2, t2.c3
 | |
|                Remote SQL: SELECT c1 FROM "S 1"."T 4" ORDER BY c1 ASC NULLS LAST
 | |
|          ->  Materialize
 | |
|                Output: t1.c1, t1.c2, t1.c3
 | |
|                ->  Foreign Scan on public.ft5 t1
 | |
|                      Output: t1.c1, t1.c2, t1.c3
 | |
|                      Remote SQL: SELECT c1 FROM "S 1"."T 4" ORDER BY c1 ASC NULLS LAST
 | |
| (13 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft5 t1 JOIN ft6 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
 | |
|  c1 | c1 
 | |
| ----+----
 | |
| (0 rows)
 | |
| 
 | |
| -- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS
 | |
| -- JOIN since c8 in both tables has same value.
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
 | |
|                                QUERY PLAN                                
 | |
| -------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1
 | |
|    ->  Sort
 | |
|          Output: t1.c1, t2.c1
 | |
|          Sort Key: t1.c1, t2.c1
 | |
|          ->  Merge Left Join
 | |
|                Output: t1.c1, t2.c1
 | |
|                Merge Cond: (t1.c8 = t2.c8)
 | |
|                ->  Sort
 | |
|                      Output: t1.c1, t1.c8
 | |
|                      Sort Key: t1.c8
 | |
|                      ->  Foreign Scan on public.ft1 t1
 | |
|                            Output: t1.c1, t1.c8
 | |
|                            Remote SQL: SELECT "C 1", c8 FROM "S 1"."T 1"
 | |
|                ->  Sort
 | |
|                      Output: t2.c1, t2.c8
 | |
|                      Sort Key: t2.c8
 | |
|                      ->  Foreign Scan on public.ft2 t2
 | |
|                            Output: t2.c1, t2.c8
 | |
|                            Remote SQL: SELECT "C 1", c8 FROM "S 1"."T 1"
 | |
| (20 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c8 = t2.c8) ORDER BY t1.c1, t2.c1 OFFSET 100 LIMIT 10;
 | |
|  c1 | c1  
 | |
| ----+-----
 | |
|   1 | 101
 | |
|   1 | 102
 | |
|   1 | 103
 | |
|   1 | 104
 | |
|   1 | 105
 | |
|   1 | 106
 | |
|   1 | 107
 | |
|   1 | 108
 | |
|   1 | 109
 | |
|   1 | 110
 | |
| (10 rows)
 | |
| 
 | |
| -- unsafe conditions on one side (c8 has a UDT), not pushed down.
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
 | |
|                                  QUERY PLAN                                  
 | |
| -----------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1, t1.c3
 | |
|    ->  Sort
 | |
|          Output: t1.c1, t2.c1, t1.c3
 | |
|          Sort Key: t1.c3, t1.c1
 | |
|          ->  Hash Right Join
 | |
|                Output: t1.c1, t2.c1, t1.c3
 | |
|                Hash Cond: (t2.c1 = t1.c1)
 | |
|                ->  Foreign Scan on public.ft2 t2
 | |
|                      Output: t2.c1
 | |
|                      Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
 | |
|                ->  Hash
 | |
|                      Output: t1.c1, t1.c3
 | |
|                      ->  Foreign Scan on public.ft1 t1
 | |
|                            Output: t1.c1, t1.c3
 | |
|                            Filter: (t1.c8 = 'foo'::user_enum)
 | |
|                            Remote SQL: SELECT "C 1", c3, c8 FROM "S 1"."T 1"
 | |
| (17 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 LEFT JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = 'foo' ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
 | |
|  c1  | c1  
 | |
| -----+-----
 | |
|  101 | 101
 | |
|  102 | 102
 | |
|  103 | 103
 | |
|  104 | 104
 | |
|  105 | 105
 | |
|  106 | 106
 | |
|  107 | 107
 | |
|  108 | 108
 | |
|  109 | 109
 | |
|  110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| -- join where unsafe to pushdown condition in WHERE clause has a column not
 | |
| -- in the SELECT clause. In this test unsafe clause needs to have column
 | |
| -- references from both joining sides so that the clause is not pushed down
 | |
| -- into one of the joining sides.
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
 | |
|                                                                       QUERY PLAN                                                                       
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, t2.c1, t1.c3
 | |
|    ->  Sort
 | |
|          Output: t1.c1, t2.c1, t1.c3
 | |
|          Sort Key: t1.c3, t1.c1
 | |
|          ->  Foreign Scan
 | |
|                Output: t1.c1, t2.c1, t1.c3
 | |
|                Filter: (t1.c8 = t2.c8)
 | |
|                Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|                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"))))
 | |
| (10 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) WHERE t1.c8 = t2.c8 ORDER BY t1.c3, t1.c1 OFFSET 100 LIMIT 10;
 | |
|  c1  | c1  
 | |
| -----+-----
 | |
|  101 | 101
 | |
|  102 | 102
 | |
|  103 | 103
 | |
|  104 | 104
 | |
|  105 | 105
 | |
|  106 | 106
 | |
|  107 | 107
 | |
|  108 | 108
 | |
|  109 | 109
 | |
|  110 | 110
 | |
| (10 rows)
 | |
| 
 | |
| -- Aggregate after UNION, for testing setrefs
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10;
 | |
|                                                                      QUERY PLAN                                                                     
 | |
| ----------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1.c1, (avg((t1.c1 + t2.c1)))
 | |
|    ->  Sort
 | |
|          Output: t1.c1, (avg((t1.c1 + t2.c1)))
 | |
|          Sort Key: t1.c1
 | |
|          ->  HashAggregate
 | |
|                Output: t1.c1, avg((t1.c1 + t2.c1))
 | |
|                Group Key: t1.c1
 | |
|                ->  HashAggregate
 | |
|                      Output: t1.c1, t2.c1
 | |
|                      Group Key: t1.c1, t2.c1
 | |
|                      ->  Append
 | |
|                            ->  Foreign Scan
 | |
|                                  Output: t1.c1, t2.c1
 | |
|                                  Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|                                  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"))))
 | |
|                            ->  Foreign Scan
 | |
|                                  Output: t1_1.c1, t2_1.c1
 | |
|                                  Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|                                  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"))))
 | |
| (20 rows)
 | |
| 
 | |
| SELECT t1c1, avg(t1c1 + t2c1) FROM (SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1) UNION SELECT t1.c1, t2.c1 FROM ft1 t1 JOIN ft2 t2 ON (t1.c1 = t2.c1)) AS t (t1c1, t2c1) GROUP BY t1c1 ORDER BY t1c1 OFFSET 100 LIMIT 10;
 | |
|  t1c1 |         avg          
 | |
| ------+----------------------
 | |
|   101 | 202.0000000000000000
 | |
|   102 | 204.0000000000000000
 | |
|   103 | 206.0000000000000000
 | |
|   104 | 208.0000000000000000
 | |
|   105 | 210.0000000000000000
 | |
|   106 | 212.0000000000000000
 | |
|   107 | 214.0000000000000000
 | |
|   108 | 216.0000000000000000
 | |
|   109 | 218.0000000000000000
 | |
|   110 | 220.0000000000000000
 | |
| (10 rows)
 | |
| 
 | |
| -- join with lateral reference
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10;
 | |
|                                                                              QUERY PLAN                                                                             
 | |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: t1."C 1"
 | |
|    ->  Nested Loop
 | |
|          Output: t1."C 1"
 | |
|          ->  Index Scan using t1_pkey on "S 1"."T 1" t1
 | |
|                Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
 | |
|          ->  HashAggregate
 | |
|                Output: t2.c1, t3.c1
 | |
|                Group Key: t2.c1, t3.c1
 | |
|                ->  Foreign Scan
 | |
|                      Output: t2.c1, t3.c1
 | |
|                      Relations: (public.ft1 t2) INNER JOIN (public.ft2 t3)
 | |
|                      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))))
 | |
| (13 rows)
 | |
| 
 | |
| SELECT t1."C 1" FROM "S 1"."T 1" t1, LATERAL (SELECT DISTINCT t2.c1, t3.c1 FROM ft1 t2, ft2 t3 WHERE t2.c1 = t3.c1 AND t2.c2 = t1.c2) q ORDER BY t1."C 1" OFFSET 10 LIMIT 10;
 | |
|  C 1 
 | |
| -----
 | |
|    1
 | |
|    1
 | |
|    1
 | |
|    1
 | |
|    1
 | |
|    1
 | |
|    1
 | |
|    1
 | |
|    1
 | |
|    1
 | |
| (10 rows)
 | |
| 
 | |
| -- non-Var items in targelist of the nullable rel of a join preventing
 | |
| -- push-down in some cases
 | |
| -- unable to push {ft1, ft2}
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15;
 | |
|                                                         QUERY PLAN                                                         
 | |
| ---------------------------------------------------------------------------------------------------------------------------
 | |
|  Nested Loop Left Join
 | |
|    Output: (13), ft2.c1
 | |
|    Join Filter: (13 = ft2.c1)
 | |
|    ->  Foreign Scan on public.ft2
 | |
|          Output: ft2.c1
 | |
|          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
 | |
|    ->  Materialize
 | |
|          Output: (13)
 | |
|          ->  Foreign Scan on public.ft1
 | |
|                Output: 13
 | |
|                Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE (("C 1" = 13))
 | |
| (11 rows)
 | |
| 
 | |
| SELECT q.a, ft2.c1 FROM (SELECT 13 FROM ft1 WHERE c1 = 13) q(a) RIGHT JOIN ft2 ON (q.a = ft2.c1) WHERE ft2.c1 BETWEEN 10 AND 15;
 | |
|  a  | c1 
 | |
| ----+----
 | |
|     | 10
 | |
|     | 11
 | |
|     | 12
 | |
|  13 | 13
 | |
|     | 14
 | |
|     | 15
 | |
| (6 rows)
 | |
| 
 | |
| -- ok to push {ft1, ft2} but not {ft1, ft2, ft4}
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15;
 | |
|                                                                                     QUERY PLAN                                                                                     
 | |
| -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Nested Loop Left Join
 | |
|    Output: ft4.c1, (13), ft1.c1, ft2.c1
 | |
|    Join Filter: (ft4.c1 = ft1.c1)
 | |
|    ->  Foreign Scan on public.ft4
 | |
|          Output: ft4.c1, ft4.c2, ft4.c3
 | |
|          Remote SQL: SELECT c1 FROM "S 1"."T 3" WHERE ((c1 >= 10)) AND ((c1 <= 15))
 | |
|    ->  Materialize
 | |
|          Output: ft1.c1, ft2.c1, (13)
 | |
|          ->  Foreign Scan
 | |
|                Output: ft1.c1, ft2.c1, 13
 | |
|                Relations: (public.ft1) INNER JOIN (public.ft2)
 | |
|                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
 | |
| (12 rows)
 | |
| 
 | |
| SELECT ft4.c1, q.* FROM ft4 LEFT JOIN (SELECT 13, ft1.c1, ft2.c1 FROM ft1 RIGHT JOIN ft2 ON (ft1.c1 = ft2.c1) WHERE ft1.c1 = 12) q(a, b, c) ON (ft4.c1 = q.b) WHERE ft4.c1 BETWEEN 10 AND 15;
 | |
|  c1 | a  | b  | c  
 | |
| ----+----+----+----
 | |
|  10 |    |    |   
 | |
|  12 | 13 | 12 | 12
 | |
|  14 |    |    |   
 | |
| (3 rows)
 | |
| 
 | |
| -- join with nullable side with some columns with null values
 | |
| UPDATE ft5 SET c3 = null where c1 % 9 = 0;
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1;
 | |
|                                                                                                                                 QUERY PLAN                                                                                                                                 
 | |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: ft5.*, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2
 | |
|    Relations: (public.ft5) INNER JOIN (public.ft4)
 | |
|    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
 | |
| (4 rows)
 | |
| 
 | |
| SELECT ft5, ft5.c1, ft5.c2, ft5.c3, ft4.c1, ft4.c2 FROM ft5 left join ft4 on ft5.c1 = ft4.c1 WHERE ft4.c1 BETWEEN 10 and 30 ORDER BY ft5.c1, ft4.c1;
 | |
|       ft5       | c1 | c2 |   c3   | c1 | c2 
 | |
| ----------------+----+----+--------+----+----
 | |
|  (12,13,AAA012) | 12 | 13 | AAA012 | 12 | 13
 | |
|  (18,19,)       | 18 | 19 |        | 18 | 19
 | |
|  (24,25,AAA024) | 24 | 25 | AAA024 | 24 | 25
 | |
|  (30,31,AAA030) | 30 | 31 | AAA030 | 30 | 31
 | |
| (4 rows)
 | |
| 
 | |
| -- check join pushdown in situations where multiple userids are involved
 | |
| CREATE ROLE regress_view_owner;
 | |
| CREATE USER MAPPING FOR regress_view_owner SERVER loopback;
 | |
| GRANT SELECT ON ft4 TO regress_view_owner;
 | |
| GRANT SELECT ON ft5 TO regress_view_owner;
 | |
| CREATE VIEW v4 AS SELECT * FROM ft4;
 | |
| CREATE VIEW v5 AS SELECT * FROM ft5;
 | |
| ALTER VIEW v5 OWNER TO regress_view_owner;
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;  -- can't be pushed down, different view owners
 | |
|                               QUERY PLAN                              
 | |
| ----------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: ft4.c1, ft5.c2, ft5.c1
 | |
|    ->  Sort
 | |
|          Output: ft4.c1, ft5.c2, ft5.c1
 | |
|          Sort Key: ft4.c1, ft5.c1
 | |
|          ->  Hash Left Join
 | |
|                Output: ft4.c1, ft5.c2, ft5.c1
 | |
|                Hash Cond: (ft4.c1 = ft5.c1)
 | |
|                ->  Foreign Scan on public.ft4
 | |
|                      Output: ft4.c1, ft4.c2, ft4.c3
 | |
|                      Remote SQL: SELECT c1 FROM "S 1"."T 3"
 | |
|                ->  Hash
 | |
|                      Output: ft5.c2, ft5.c1
 | |
|                      ->  Foreign Scan on public.ft5
 | |
|                            Output: ft5.c2, ft5.c1
 | |
|                            Remote SQL: SELECT c1, c2 FROM "S 1"."T 4"
 | |
| (16 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
 | |
|  c1 | c2 
 | |
| ----+----
 | |
|  22 |   
 | |
|  24 | 25
 | |
|  26 |   
 | |
|  28 |   
 | |
|  30 | 31
 | |
|  32 |   
 | |
|  34 |   
 | |
|  36 | 37
 | |
|  38 |   
 | |
|  40 |   
 | |
| (10 rows)
 | |
| 
 | |
| ALTER VIEW v4 OWNER TO regress_view_owner;
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;  -- can be pushed down
 | |
|                                                                                 QUERY PLAN                                                                                
 | |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: ft4.c1, ft5.c2, ft5.c1
 | |
|    ->  Foreign Scan
 | |
|          Output: ft4.c1, ft5.c2, ft5.c1
 | |
|          Relations: (public.ft4) LEFT JOIN (public.ft5)
 | |
|          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
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN v5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
 | |
|  c1 | c2 
 | |
| ----+----
 | |
|  22 |   
 | |
|  24 | 25
 | |
|  26 |   
 | |
|  28 |   
 | |
|  30 | 31
 | |
|  32 |   
 | |
|  34 |   
 | |
|  36 | 37
 | |
|  38 |   
 | |
|  40 |   
 | |
| (10 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;  -- can't be pushed down, view owner not current user
 | |
|                               QUERY PLAN                              
 | |
| ----------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: ft4.c1, t2.c2, t2.c1
 | |
|    ->  Sort
 | |
|          Output: ft4.c1, t2.c2, t2.c1
 | |
|          Sort Key: ft4.c1, t2.c1
 | |
|          ->  Hash Left Join
 | |
|                Output: ft4.c1, t2.c2, t2.c1
 | |
|                Hash Cond: (ft4.c1 = t2.c1)
 | |
|                ->  Foreign Scan on public.ft4
 | |
|                      Output: ft4.c1, ft4.c2, ft4.c3
 | |
|                      Remote SQL: SELECT c1 FROM "S 1"."T 3"
 | |
|                ->  Hash
 | |
|                      Output: t2.c2, t2.c1
 | |
|                      ->  Foreign Scan on public.ft5 t2
 | |
|                            Output: t2.c2, t2.c1
 | |
|                            Remote SQL: SELECT c1, c2 FROM "S 1"."T 4"
 | |
| (16 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
 | |
|  c1 | c2 
 | |
| ----+----
 | |
|  22 |   
 | |
|  24 | 25
 | |
|  26 |   
 | |
|  28 |   
 | |
|  30 | 31
 | |
|  32 |   
 | |
|  34 |   
 | |
|  36 | 37
 | |
|  38 |   
 | |
|  40 |   
 | |
| (10 rows)
 | |
| 
 | |
| ALTER VIEW v4 OWNER TO CURRENT_USER;
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;  -- can be pushed down
 | |
|                                                                                 QUERY PLAN                                                                                
 | |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: ft4.c1, t2.c2, t2.c1
 | |
|    ->  Foreign Scan
 | |
|          Output: ft4.c1, t2.c2, t2.c1
 | |
|          Relations: (public.ft4) LEFT JOIN (public.ft5 t2)
 | |
|          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
 | |
| (6 rows)
 | |
| 
 | |
| SELECT t1.c1, t2.c2 FROM v4 t1 LEFT JOIN ft5 t2 ON (t1.c1 = t2.c1) ORDER BY t1.c1, t2.c1 OFFSET 10 LIMIT 10;
 | |
|  c1 | c2 
 | |
| ----+----
 | |
|  22 |   
 | |
|  24 | 25
 | |
|  26 |   
 | |
|  28 |   
 | |
|  30 | 31
 | |
|  32 |   
 | |
|  34 |   
 | |
|  36 | 37
 | |
|  38 |   
 | |
|  40 |   
 | |
| (10 rows)
 | |
| 
 | |
| ALTER VIEW v4 OWNER TO regress_view_owner;
 | |
| -- cleanup
 | |
| DROP OWNED BY regress_view_owner;
 | |
| DROP ROLE regress_view_owner;
 | |
| -- ===================================================================
 | |
| -- Aggregate and grouping queries
 | |
| -- ===================================================================
 | |
| -- Simple aggregates
 | |
| explain (verbose, costs off)
 | |
| select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2;
 | |
|                                                                       QUERY PLAN                                                                       
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Result
 | |
|    Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), ((sum(c1)) * ((random() <= '1'::double precision))::integer), c2
 | |
|    ->  Sort
 | |
|          Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2
 | |
|          Sort Key: (count(ft1.c6)), (sum(ft1.c1))
 | |
|          ->  Foreign Scan
 | |
|                Output: (count(c6)), (sum(c1)), (avg(c1)), (min(c2)), (max(c1)), (stddev(c2)), c2
 | |
|                Relations: Aggregate on (public.ft1)
 | |
|                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 c2
 | |
| (9 rows)
 | |
| 
 | |
| select count(c6), sum(c1), avg(c1), min(c2), max(c1), stddev(c2), sum(c1) * (random() <= 1)::int as sum2 from ft1 where c2 < 5 group by c2 order by 1, 2;
 | |
|  count |  sum  |         avg          | min | max  | stddev | sum2  
 | |
| -------+-------+----------------------+-----+------+--------+-------
 | |
|    100 | 49600 | 496.0000000000000000 |   1 |  991 |      0 | 49600
 | |
|    100 | 49700 | 497.0000000000000000 |   2 |  992 |      0 | 49700
 | |
|    100 | 49800 | 498.0000000000000000 |   3 |  993 |      0 | 49800
 | |
|    100 | 49900 | 499.0000000000000000 |   4 |  994 |      0 | 49900
 | |
|    100 | 50500 | 505.0000000000000000 |   0 | 1000 |      0 | 50500
 | |
| (5 rows)
 | |
| 
 | |
| -- Aggregate is not pushed down as aggregation contains random()
 | |
| explain (verbose, costs off)
 | |
| select sum(c1 * (random() <= 1)::int) as sum, avg(c1) from ft1;
 | |
|                                   QUERY PLAN                                   
 | |
| -------------------------------------------------------------------------------
 | |
|  Aggregate
 | |
|    Output: sum((c1 * ((random() <= '1'::double precision))::integer)), avg(c1)
 | |
|    ->  Foreign Scan on public.ft1
 | |
|          Output: c1
 | |
|          Remote SQL: SELECT "C 1" FROM "S 1"."T 1"
 | |
| (5 rows)
 | |
| 
 | |
| -- Aggregate over join query
 | |
| explain (verbose, costs off)
 | |
| select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6;
 | |
|                                                                     QUERY PLAN                                                                    
 | |
| --------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: (count(*)), (sum(t1.c1)), (avg(t2.c1))
 | |
|    Relations: Aggregate on ((public.ft1 t1) INNER JOIN (public.ft1 t2))
 | |
|    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))))
 | |
| (4 rows)
 | |
| 
 | |
| select count(*), sum(t1.c1), avg(t2.c1) from ft1 t1 inner join ft1 t2 on (t1.c2 = t2.c2) where t1.c2 = 6;
 | |
|  count |   sum   |         avg          
 | |
| -------+---------+----------------------
 | |
|  10000 | 5010000 | 501.0000000000000000
 | |
| (1 row)
 | |
| 
 | |
| -- Not pushed down due to local conditions present in underneath input rel
 | |
| explain (verbose, costs off)
 | |
| select sum(t1.c1), count(t2.c1) from ft1 t1 inner join ft2 t2 on (t1.c1 = t2.c1) where ((t1.c1 * t2.c1)/(t1.c1 * t2.c1)) * random() <= 1;
 | |
|                                                          QUERY PLAN                                                         
 | |
| ----------------------------------------------------------------------------------------------------------------------------
 | |
|  Aggregate
 | |
|    Output: sum(t1.c1), count(t2.c1)
 | |
|    ->  Foreign Scan
 | |
|          Output: t1.c1, t2.c1
 | |
|          Filter: (((((t1.c1 * t2.c1) / (t1.c1 * t2.c1)))::double precision * random()) <= '1'::double precision)
 | |
|          Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|          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"))))
 | |
| (7 rows)
 | |
| 
 | |
| -- GROUP BY clause having expressions
 | |
| explain (verbose, costs off)
 | |
| select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
 | |
|                                            QUERY PLAN                                           
 | |
| ------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: ((c2 / 2)), ((sum(c2) * (c2 / 2)))
 | |
|    Sort Key: ((ft1.c2 / 2))
 | |
|    ->  Foreign Scan
 | |
|          Output: ((c2 / 2)), ((sum(c2) * (c2 / 2)))
 | |
|          Relations: Aggregate on (public.ft1)
 | |
|          Remote SQL: SELECT (c2 / 2), (sum(c2) * (c2 / 2)) FROM "S 1"."T 1" GROUP BY ((c2 / 2))
 | |
| (7 rows)
 | |
| 
 | |
| select c2/2, sum(c2) * (c2/2) from ft1 group by c2/2 order by c2/2;
 | |
|  ?column? | ?column? 
 | |
| ----------+----------
 | |
|         0 |        0
 | |
|         1 |      500
 | |
|         2 |     1800
 | |
|         3 |     3900
 | |
|         4 |     6800
 | |
| (5 rows)
 | |
| 
 | |
| -- Aggregates in subquery are pushed down.
 | |
| explain (verbose, costs off)
 | |
| select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x;
 | |
|                                                 QUERY PLAN                                                
 | |
| ----------------------------------------------------------------------------------------------------------
 | |
|  Aggregate
 | |
|    Output: count(ft1.c2), sum(ft1.c2)
 | |
|    ->  Sort
 | |
|          Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision))
 | |
|          Sort Key: ft1.c2, (sum(ft1.c1))
 | |
|          ->  Foreign Scan
 | |
|                Output: ft1.c2, (sum(ft1.c1)), (sqrt((ft1.c1)::double precision))
 | |
|                Relations: Aggregate on (public.ft1)
 | |
|                Remote SQL: SELECT c2, sum("C 1"), sqrt("C 1") FROM "S 1"."T 1" GROUP BY c2, (sqrt("C 1"))
 | |
| (9 rows)
 | |
| 
 | |
| select count(x.a), sum(x.a) from (select c2 a, sum(c1) b from ft1 group by c2, sqrt(c1) order by 1, 2) x;
 | |
|  count | sum  
 | |
| -------+------
 | |
|   1000 | 4500
 | |
| (1 row)
 | |
| 
 | |
| -- Aggregate is still pushed down by taking unshippable expression out
 | |
| explain (verbose, costs off)
 | |
| select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2;
 | |
|                                             QUERY PLAN                                             
 | |
| ---------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: ((c2 * ((random() <= '1'::double precision))::integer)), ((sum(c1) * c2)), c2
 | |
|    Sort Key: ((ft1.c2 * ((random() <= '1'::double precision))::integer)), ((sum(ft1.c1) * ft1.c2))
 | |
|    ->  Foreign Scan
 | |
|          Output: (c2 * ((random() <= '1'::double precision))::integer), ((sum(c1) * c2)), c2
 | |
|          Relations: Aggregate on (public.ft1)
 | |
|          Remote SQL: SELECT (sum("C 1") * c2), c2 FROM "S 1"."T 1" GROUP BY c2
 | |
| (7 rows)
 | |
| 
 | |
| select c2 * (random() <= 1)::int as sum1, sum(c1) * c2 as sum2 from ft1 group by c2 order by 1, 2;
 | |
|  sum1 |  sum2  
 | |
| ------+--------
 | |
|     0 |      0
 | |
|     1 |  49600
 | |
|     2 |  99400
 | |
|     3 | 149400
 | |
|     4 | 199600
 | |
|     5 | 250000
 | |
|     6 | 300600
 | |
|     7 | 351400
 | |
|     8 | 402400
 | |
|     9 | 453600
 | |
| (10 rows)
 | |
| 
 | |
| -- Aggregate with unshippable GROUP BY clause are not pushed
 | |
| explain (verbose, costs off)
 | |
| select c2 * (random() <= 1)::int as c2 from ft2 group by c2 * (random() <= 1)::int order by 1;
 | |
|                                   QUERY PLAN                                  
 | |
| ------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: ((c2 * ((random() <= '1'::double precision))::integer))
 | |
|    Sort Key: ((ft2.c2 * ((random() <= '1'::double precision))::integer))
 | |
|    ->  HashAggregate
 | |
|          Output: ((c2 * ((random() <= '1'::double precision))::integer))
 | |
|          Group Key: (ft2.c2 * ((random() <= '1'::double precision))::integer)
 | |
|          ->  Foreign Scan on public.ft2
 | |
|                Output: (c2 * ((random() <= '1'::double precision))::integer)
 | |
|                Remote SQL: SELECT c2 FROM "S 1"."T 1"
 | |
| (9 rows)
 | |
| 
 | |
| -- GROUP BY clause in various forms, cardinal, alias and constant expression
 | |
| explain (verbose, costs off)
 | |
| select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2;
 | |
|                                                 QUERY PLAN                                                
 | |
| ----------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (count(c2)), c2, 5, 7.0, 9
 | |
|    Sort Key: ft1.c2
 | |
|    ->  Foreign Scan
 | |
|          Output: (count(c2)), c2, 5, 7.0, 9
 | |
|          Relations: Aggregate on (public.ft1)
 | |
|          Remote SQL: SELECT count(c2), c2, 5, 7.0, 9 FROM "S 1"."T 1" GROUP BY c2, 5::integer, 9::integer
 | |
| (7 rows)
 | |
| 
 | |
| select count(c2) w, c2 x, 5 y, 7.0 z from ft1 group by 2, y, 9.0::int order by 2;
 | |
|   w  | x | y |  z  
 | |
| -----+---+---+-----
 | |
|  100 | 0 | 5 | 7.0
 | |
|  100 | 1 | 5 | 7.0
 | |
|  100 | 2 | 5 | 7.0
 | |
|  100 | 3 | 5 | 7.0
 | |
|  100 | 4 | 5 | 7.0
 | |
|  100 | 5 | 5 | 7.0
 | |
|  100 | 6 | 5 | 7.0
 | |
|  100 | 7 | 5 | 7.0
 | |
|  100 | 8 | 5 | 7.0
 | |
|  100 | 9 | 5 | 7.0
 | |
| (10 rows)
 | |
| 
 | |
| -- Testing HAVING clause shippability
 | |
| explain (verbose, costs off)
 | |
| select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
 | |
|                                                                QUERY PLAN                                                               
 | |
| ----------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: c2, (sum(c1))
 | |
|    Sort Key: ft2.c2
 | |
|    ->  Foreign Scan
 | |
|          Output: c2, (sum(c1))
 | |
|          Relations: Aggregate on (public.ft2)
 | |
|          Remote SQL: SELECT c2, sum("C 1") FROM "S 1"."T 1" GROUP BY c2 HAVING ((avg("C 1") < 500::numeric)) AND ((sum("C 1") < 49800))
 | |
| (7 rows)
 | |
| 
 | |
| select c2, sum(c1) from ft2 group by c2 having avg(c1) < 500 and sum(c1) < 49800 order by c2;
 | |
|  c2 |  sum  
 | |
| ----+-------
 | |
|   1 | 49600
 | |
|   2 | 49700
 | |
| (2 rows)
 | |
| 
 | |
| -- Unshippable HAVING clause will be evaluated locally, and other qual in HAVING clause is pushed down
 | |
| explain (verbose, costs off)
 | |
| select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x;
 | |
|                                                                    QUERY PLAN                                                                    
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Aggregate
 | |
|    Output: count(*)
 | |
|    ->  Foreign Scan
 | |
|          Output: ft1.c5, NULL::bigint, (sqrt((ft1.c2)::double precision))
 | |
|          Filter: (((((avg(ft1.c1)) / (avg(ft1.c1))))::double precision * random()) <= '1'::double precision)
 | |
|          Relations: Aggregate on (public.ft1)
 | |
|          Remote SQL: SELECT c5, NULL::bigint, sqrt(c2), avg("C 1") FROM "S 1"."T 1" GROUP BY c5, (sqrt(c2)) HAVING ((avg("C 1") < 500::numeric))
 | |
| (7 rows)
 | |
| 
 | |
| select count(*) from (select c5, count(c1) from ft1 group by c5, sqrt(c2) having (avg(c1) / avg(c1)) * random() <= 1 and avg(c1) < 500) x;
 | |
|  count 
 | |
| -------
 | |
|     49
 | |
| (1 row)
 | |
| 
 | |
| -- Aggregate in HAVING clause is not pushable, and thus aggregation is not pushed down
 | |
| explain (verbose, costs off)
 | |
| select sum(c1) from ft1 group by c2 having avg(c1 * (random() <= 1)::int) > 100 order by 1;
 | |
|                                             QUERY PLAN                                             
 | |
| ---------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (sum(c1)), c2
 | |
|    Sort Key: (sum(ft1.c1))
 | |
|    ->  HashAggregate
 | |
|          Output: sum(c1), c2
 | |
|          Group Key: ft1.c2
 | |
|          Filter: (avg((ft1.c1 * ((random() <= '1'::double precision))::integer)) > '100'::numeric)
 | |
|          ->  Foreign Scan on public.ft1
 | |
|                Output: c2, c1
 | |
|                Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1"
 | |
| (10 rows)
 | |
| 
 | |
| -- Testing ORDER BY, DISTINCT, FILTER, Ordered-sets and VARIADIC within aggregates
 | |
| -- ORDER BY within aggregate, same column used to order
 | |
| explain (verbose, costs off)
 | |
| select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1;
 | |
|                                                             QUERY PLAN                                                            
 | |
| ----------------------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (array_agg(c1 ORDER BY c1)), c2
 | |
|    Sort Key: (array_agg(ft1.c1 ORDER BY ft1.c1))
 | |
|    ->  Foreign Scan
 | |
|          Output: (array_agg(c1 ORDER BY c1)), c2
 | |
|          Relations: Aggregate on (public.ft1)
 | |
|          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 c2
 | |
| (7 rows)
 | |
| 
 | |
| select array_agg(c1 order by c1) from ft1 where c1 < 100 group by c2 order by 1;
 | |
|            array_agg            
 | |
| --------------------------------
 | |
|  {1,11,21,31,41,51,61,71,81,91}
 | |
|  {2,12,22,32,42,52,62,72,82,92}
 | |
|  {3,13,23,33,43,53,63,73,83,93}
 | |
|  {4,14,24,34,44,54,64,74,84,94}
 | |
|  {5,15,25,35,45,55,65,75,85,95}
 | |
|  {6,16,26,36,46,56,66,76,86,96}
 | |
|  {7,17,27,37,47,57,67,77,87,97}
 | |
|  {8,18,28,38,48,58,68,78,88,98}
 | |
|  {9,19,29,39,49,59,69,79,89,99}
 | |
|  {10,20,30,40,50,60,70,80,90}
 | |
| (10 rows)
 | |
| 
 | |
| -- ORDER BY within aggregate, different column used to order also using DESC
 | |
| explain (verbose, costs off)
 | |
| select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50;
 | |
|                                                        QUERY PLAN                                                        
 | |
| -------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: (array_agg(c5 ORDER BY c1 DESC))
 | |
|    Relations: Aggregate on (public.ft2)
 | |
|    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))
 | |
| (4 rows)
 | |
| 
 | |
| select array_agg(c5 order by c1 desc) from ft2 where c2 = 6 and c1 < 50;
 | |
|                                                                 array_agg                                                                 
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  {"Mon Feb 16 00:00:00 1970","Fri Feb 06 00:00:00 1970","Tue Jan 27 00:00:00 1970","Sat Jan 17 00:00:00 1970","Wed Jan 07 00:00:00 1970"}
 | |
| (1 row)
 | |
| 
 | |
| -- DISTINCT within aggregate
 | |
| explain (verbose, costs off)
 | |
| select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
 | |
|                                                                                                             QUERY PLAN                                                                                                            
 | |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (array_agg(DISTINCT (t1.c1 % 5))), ((t2.c1 % 3))
 | |
|    Sort Key: (array_agg(DISTINCT (t1.c1 % 5)))
 | |
|    ->  Foreign Scan
 | |
|          Output: (array_agg(DISTINCT (t1.c1 % 5))), ((t2.c1 % 3))
 | |
|          Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
 | |
|          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 ((r2.c1 % 3))
 | |
| (7 rows)
 | |
| 
 | |
| select array_agg(distinct (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
 | |
|   array_agg   
 | |
| --------------
 | |
|  {0,1,2,3,4}
 | |
|  {1,2,3,NULL}
 | |
| (2 rows)
 | |
| 
 | |
| -- DISTINCT combined with ORDER BY within aggregate
 | |
| explain (verbose, costs off)
 | |
| select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
 | |
|                                                                                                                                QUERY PLAN                                                                                                                               
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))), ((t2.c1 % 3))
 | |
|    Sort Key: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5)))
 | |
|    ->  Foreign Scan
 | |
|          Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5))), ((t2.c1 % 3))
 | |
|          Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
 | |
|          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 ((r2.c1 % 3))
 | |
| (7 rows)
 | |
| 
 | |
| select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
 | |
|   array_agg   
 | |
| --------------
 | |
|  {0,1,2,3,4}
 | |
|  {1,2,3,NULL}
 | |
| (2 rows)
 | |
| 
 | |
| explain (verbose, costs off)
 | |
| select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
 | |
|                                                                                                                                QUERY PLAN                                                                                                                                
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)), ((t2.c1 % 3))
 | |
|    Sort Key: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST))
 | |
|    ->  Foreign Scan
 | |
|          Output: (array_agg(DISTINCT (t1.c1 % 5) ORDER BY (t1.c1 % 5) DESC NULLS LAST)), ((t2.c1 % 3))
 | |
|          Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
 | |
|          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 ((r2.c1 % 3))
 | |
| (7 rows)
 | |
| 
 | |
| select array_agg(distinct (t1.c1)%5 order by (t1.c1)%5 desc nulls last) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) where t1.c1 < 20 or (t1.c1 is null and t2.c1 < 5) group by (t2.c1)%3 order by 1;
 | |
|   array_agg   
 | |
| --------------
 | |
|  {3,2,1,NULL}
 | |
|  {4,3,2,1,0}
 | |
| (2 rows)
 | |
| 
 | |
| -- FILTER within aggregate
 | |
| explain (verbose, costs off)
 | |
| select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last;
 | |
|                                                      QUERY PLAN                                                     
 | |
| --------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2
 | |
|    Sort Key: (sum(ft1.c1) FILTER (WHERE ((ft1.c1 < 100) AND (ft1.c2 > 5))))
 | |
|    ->  Foreign Scan
 | |
|          Output: (sum(c1) FILTER (WHERE ((c1 < 100) AND (c2 > 5)))), c2
 | |
|          Relations: Aggregate on (public.ft1)
 | |
|          Remote SQL: SELECT sum("C 1") FILTER (WHERE (("C 1" < 100) AND (c2 > 5))), c2 FROM "S 1"."T 1" GROUP BY c2
 | |
| (7 rows)
 | |
| 
 | |
| select sum(c1) filter (where c1 < 100 and c2 > 5) from ft1 group by c2 order by 1 nulls last;
 | |
|  sum 
 | |
| -----
 | |
|  510
 | |
|  520
 | |
|  530
 | |
|  540
 | |
|     
 | |
|     
 | |
|     
 | |
|     
 | |
|     
 | |
|     
 | |
| (10 rows)
 | |
| 
 | |
| -- DISTINCT, ORDER BY and FILTER within aggregate
 | |
| explain (verbose, costs off)
 | |
| select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2;
 | |
|                                                                                         QUERY PLAN                                                                                         
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: (sum((c1 % 3))), (sum(DISTINCT (c1 % 3) ORDER BY (c1 % 3)) FILTER (WHERE ((c1 % 3) < 2))), c2
 | |
|    Relations: Aggregate on (public.ft1)
 | |
|    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 c2
 | |
| (4 rows)
 | |
| 
 | |
| select sum(c1%3), sum(distinct c1%3 order by c1%3) filter (where c1%3 < 2), c2 from ft1 where c2 = 6 group by c2;
 | |
|  sum | sum | c2 
 | |
| -----+-----+----
 | |
|   99 |   1 |  6
 | |
| (1 row)
 | |
| 
 | |
| -- Outer query is aggregation query
 | |
| explain (verbose, costs off)
 | |
| select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 order by 1;
 | |
|                                               QUERY PLAN                                               
 | |
| -------------------------------------------------------------------------------------------------------
 | |
|  Unique
 | |
|    Output: ((SubPlan 1))
 | |
|    ->  Sort
 | |
|          Output: ((SubPlan 1))
 | |
|          Sort Key: ((SubPlan 1))
 | |
|          ->  Foreign Scan
 | |
|                Output: (SubPlan 1)
 | |
|                Relations: Aggregate on (public.ft2 t2)
 | |
|                Remote SQL: SELECT count(*) FILTER (WHERE ((c2 = 6) AND ("C 1" < 10))) FROM "S 1"."T 1"
 | |
|                SubPlan 1
 | |
|                  ->  Foreign Scan on public.ft1 t1
 | |
|                        Output: (count(*) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))))
 | |
|                        Remote SQL: SELECT NULL FROM "S 1"."T 1" WHERE (("C 1" = 6))
 | |
| (13 rows)
 | |
| 
 | |
| select distinct (select count(*) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 order by 1;
 | |
|  count 
 | |
| -------
 | |
|      1
 | |
| (1 row)
 | |
| 
 | |
| -- Inner query is aggregation query
 | |
| explain (verbose, costs off)
 | |
| select distinct (select count(t1.c1) filter (where t2.c2 = 6 and t2.c1 < 10) from ft1 t1 where t1.c1 = 6) from ft2 t2 order by 1;
 | |
|                                                                       QUERY PLAN                                                                      
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Unique
 | |
|    Output: ((SubPlan 1))
 | |
|    ->  Sort
 | |
|          Output: ((SubPlan 1))
 | |
|          Sort Key: ((SubPlan 1))
 | |
|          ->  Foreign Scan on public.ft2 t2
 | |
|                Output: (SubPlan 1)
 | |
|                Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1"
 | |
|                SubPlan 1
 | |
|                  ->  Foreign Scan
 | |
|                        Output: (count(t1.c1) FILTER (WHERE ((t2.c2 = 6) AND (t2.c1 < 10))))
 | |
|                        Relations: Aggregate on (public.ft1 t1)
 | |
|                        Remote SQL: SELECT count("C 1") FILTER (WHERE (($1::integer = 6) AND ($2::integer < 10))) FROM "S 1"."T 1" WHERE (("C 1" = 6))
 | |
| (13 rows)
 | |
| 
 | |
| 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 order by 1;
 | |
|  count 
 | |
| -------
 | |
|      0
 | |
|      1
 | |
| (2 rows)
 | |
| 
 | |
| -- Aggregate not pushed down as FILTER condition is not pushable
 | |
| explain (verbose, costs off)
 | |
| select sum(c1) filter (where (c1 / c1) * random() <= 1) from ft1 group by c2 order by 1;
 | |
|                                                        QUERY PLAN                                                       
 | |
| ------------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision))), c2
 | |
|    Sort Key: (sum(ft1.c1) FILTER (WHERE ((((ft1.c1 / ft1.c1))::double precision * random()) <= '1'::double precision)))
 | |
|    ->  HashAggregate
 | |
|          Output: sum(c1) FILTER (WHERE ((((c1 / c1))::double precision * random()) <= '1'::double precision)), c2
 | |
|          Group Key: ft1.c2
 | |
|          ->  Foreign Scan on public.ft1
 | |
|                Output: c2, c1
 | |
|                Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1"
 | |
| (9 rows)
 | |
| 
 | |
| explain (verbose, costs off)
 | |
| select sum(c2) filter (where c2 in (select c2 from ft1 where c2 < 5)) from ft1;
 | |
|                             QUERY PLAN                             
 | |
| -------------------------------------------------------------------
 | |
|  Aggregate
 | |
|    Output: sum(ft1.c2) FILTER (WHERE (hashed SubPlan 1))
 | |
|    ->  Foreign Scan on public.ft1
 | |
|          Output: ft1.c2
 | |
|          Remote SQL: SELECT c2 FROM "S 1"."T 1"
 | |
|    SubPlan 1
 | |
|      ->  Foreign Scan on public.ft1 ft1_1
 | |
|            Output: ft1_1.c2
 | |
|            Remote SQL: SELECT c2 FROM "S 1"."T 1" WHERE ((c2 < 5))
 | |
| (9 rows)
 | |
| 
 | |
| -- Ordered-sets within aggregate
 | |
| explain (verbose, costs off)
 | |
| select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2;
 | |
|                                                                                                                                                                            QUERY PLAN                                                                                                                                                                            
 | |
| -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    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)))
 | |
|    Sort Key: ft1.c2
 | |
|    ->  Foreign Scan
 | |
|          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)))
 | |
|          Relations: Aggregate on (public.ft1)
 | |
|          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 c2 HAVING ((percentile_cont((c2 / 10::numeric)) WITHIN GROUP (ORDER BY ("C 1") ASC NULLS LAST) < 500::double precision))
 | |
| (7 rows)
 | |
| 
 | |
| select c2, rank('10'::varchar) within group (order by c6), percentile_cont(c2/10::numeric) within group (order by c1) from ft1 where c2 < 10 group by c2 having percentile_cont(c2/10::numeric) within group (order by c1) < 500 order by c2;
 | |
|  c2 | rank | percentile_cont 
 | |
| ----+------+-----------------
 | |
|   0 |  101 |              10
 | |
|   1 |  101 |             100
 | |
|   2 |    1 |             200
 | |
|   3 |    1 |             300
 | |
|   4 |    1 |             400
 | |
| (5 rows)
 | |
| 
 | |
| -- Using multiple arguments within aggregates
 | |
| explain (verbose, costs off)
 | |
| select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1;
 | |
|                                                                                QUERY PLAN                                                                                
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: c1, (rank(c1, c2) WITHIN GROUP (ORDER BY c1, c2)), c2
 | |
|    Relations: Aggregate on (public.ft1)
 | |
|    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 "C 1", c2
 | |
| (4 rows)
 | |
| 
 | |
| select c1, rank(c1, c2) within group (order by c1, c2) from ft1 group by c1, c2 having c1 = 6 order by 1;
 | |
|  c1 | rank 
 | |
| ----+------
 | |
|   6 |    1
 | |
| (1 row)
 | |
| 
 | |
| -- User defined function for user defined aggregate, VARIADIC
 | |
| create function least_accum(anyelement, variadic anyarray)
 | |
| returns anyelement language sql as
 | |
|   'select least($1, min($2[i])) from generate_subscripts($2,1) g(i)';
 | |
| create aggregate least_agg(variadic items anyarray) (
 | |
|   stype = anyelement, sfunc = least_accum
 | |
| );
 | |
| -- Disable hash aggregation for plan stability.
 | |
| set enable_hashagg to false;
 | |
| -- Not pushed down due to user defined aggregate
 | |
| explain (verbose, costs off)
 | |
| select c2, least_agg(c1) from ft1 group by c2 order by c2;
 | |
|                                     QUERY PLAN                                    
 | |
| ----------------------------------------------------------------------------------
 | |
|  GroupAggregate
 | |
|    Output: c2, least_agg(VARIADIC ARRAY[c1])
 | |
|    Group Key: ft1.c2
 | |
|    ->  Foreign Scan on public.ft1
 | |
|          Output: c2, c1
 | |
|          Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
 | |
| (6 rows)
 | |
| 
 | |
| -- Add function and aggregate into extension
 | |
| alter extension postgres_fdw add function least_accum(anyelement, variadic anyarray);
 | |
| alter extension postgres_fdw add aggregate least_agg(variadic items anyarray);
 | |
| alter server loopback options (set extensions 'postgres_fdw');
 | |
| -- Now aggregate will be pushed.  Aggregate will display VARIADIC argument.
 | |
| explain (verbose, costs off)
 | |
| select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2;
 | |
|                                                        QUERY PLAN                                                       
 | |
| ------------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: c2, (least_agg(VARIADIC ARRAY[c1]))
 | |
|    Sort Key: ft1.c2
 | |
|    ->  Foreign Scan
 | |
|          Output: c2, (least_agg(VARIADIC ARRAY[c1]))
 | |
|          Relations: Aggregate on (public.ft1)
 | |
|          Remote SQL: SELECT c2, public.least_agg(VARIADIC ARRAY["C 1"]) FROM "S 1"."T 1" WHERE ((c2 < 100)) GROUP BY c2
 | |
| (7 rows)
 | |
| 
 | |
| select c2, least_agg(c1) from ft1 where c2 < 100 group by c2 order by c2;
 | |
|  c2 | least_agg 
 | |
| ----+-----------
 | |
|   0 |        10
 | |
|   1 |         1
 | |
|   2 |         2
 | |
|   3 |         3
 | |
|   4 |         4
 | |
|   5 |         5
 | |
|   6 |         6
 | |
|   7 |         7
 | |
|   8 |         8
 | |
|   9 |         9
 | |
| (10 rows)
 | |
| 
 | |
| -- Remove function and aggregate from extension
 | |
| alter extension postgres_fdw drop function least_accum(anyelement, variadic anyarray);
 | |
| alter extension postgres_fdw drop aggregate least_agg(variadic items anyarray);
 | |
| alter server loopback options (set extensions 'postgres_fdw');
 | |
| -- Not pushed down as we have dropped objects from extension.
 | |
| explain (verbose, costs off)
 | |
| select c2, least_agg(c1) from ft1 group by c2 order by c2;
 | |
|                                     QUERY PLAN                                    
 | |
| ----------------------------------------------------------------------------------
 | |
|  GroupAggregate
 | |
|    Output: c2, least_agg(VARIADIC ARRAY[c1])
 | |
|    Group Key: ft1.c2
 | |
|    ->  Foreign Scan on public.ft1
 | |
|          Output: c2, c1
 | |
|          Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" ORDER BY c2 ASC NULLS LAST
 | |
| (6 rows)
 | |
| 
 | |
| -- Cleanup
 | |
| reset enable_hashagg;
 | |
| drop aggregate least_agg(variadic items anyarray);
 | |
| drop function least_accum(anyelement, variadic anyarray);
 | |
| -- Testing USING OPERATOR() in ORDER BY within aggregate.
 | |
| -- For this, we need user defined operators along with operator family and
 | |
| -- operator class.  Create those and then add them in extension.  Note that
 | |
| -- user defined objects are considered unshippable unless they are part of
 | |
| -- the extension.
 | |
| create operator public.<^ (
 | |
|  leftarg = int4,
 | |
|  rightarg = int4,
 | |
|  procedure = int4eq
 | |
| );
 | |
| create operator public.=^ (
 | |
|  leftarg = int4,
 | |
|  rightarg = int4,
 | |
|  procedure = int4lt
 | |
| );
 | |
| create operator public.>^ (
 | |
|  leftarg = int4,
 | |
|  rightarg = int4,
 | |
|  procedure = int4gt
 | |
| );
 | |
| create operator family my_op_family using btree;
 | |
| create function my_op_cmp(a int, b int) returns int as
 | |
|   $$begin return btint4cmp(a, b); end $$ language plpgsql;
 | |
| create operator class my_op_class for type int using btree family my_op_family as
 | |
|  operator 1 public.<^,
 | |
|  operator 3 public.=^,
 | |
|  operator 5 public.>^,
 | |
|  function 1 my_op_cmp(int, int);
 | |
| -- This will not be pushed as user defined sort operator is not part of the
 | |
| -- extension yet.
 | |
| explain (verbose, costs off)
 | |
| select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
 | |
|                                          QUERY PLAN                                         
 | |
| --------------------------------------------------------------------------------------------
 | |
|  GroupAggregate
 | |
|    Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2
 | |
|    Group Key: ft2.c2
 | |
|    ->  Foreign Scan on public.ft2
 | |
|          Output: c2, c1
 | |
|          Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6))
 | |
| (6 rows)
 | |
| 
 | |
| -- Add into extension
 | |
| alter extension postgres_fdw add operator class my_op_class using btree;
 | |
| alter extension postgres_fdw add function my_op_cmp(a int, b int);
 | |
| alter extension postgres_fdw add operator family my_op_family using btree;
 | |
| alter extension postgres_fdw add operator public.<^(int, int);
 | |
| alter extension postgres_fdw add operator public.=^(int, int);
 | |
| alter extension postgres_fdw add operator public.>^(int, int);
 | |
| alter server loopback options (set extensions 'postgres_fdw');
 | |
| -- Now this will be pushed as sort operator is part of the extension.
 | |
| explain (verbose, costs off)
 | |
| select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
 | |
|                                                                            QUERY PLAN                                                                            
 | |
| -----------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: (array_agg(c1 ORDER BY c1 USING <^ NULLS LAST)), c2
 | |
|    Relations: Aggregate on (public.ft2)
 | |
|    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 c2
 | |
| (4 rows)
 | |
| 
 | |
| select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
 | |
|            array_agg            
 | |
| --------------------------------
 | |
|  {6,16,26,36,46,56,66,76,86,96}
 | |
| (1 row)
 | |
| 
 | |
| -- Remove from extension
 | |
| alter extension postgres_fdw drop operator class my_op_class using btree;
 | |
| alter extension postgres_fdw drop function my_op_cmp(a int, b int);
 | |
| alter extension postgres_fdw drop operator family my_op_family using btree;
 | |
| alter extension postgres_fdw drop operator public.<^(int, int);
 | |
| alter extension postgres_fdw drop operator public.=^(int, int);
 | |
| alter extension postgres_fdw drop operator public.>^(int, int);
 | |
| alter server loopback options (set extensions 'postgres_fdw');
 | |
| -- This will not be pushed as sort operator is now removed from the extension.
 | |
| explain (verbose, costs off)
 | |
| select array_agg(c1 order by c1 using operator(public.<^)) from ft2 where c2 = 6 and c1 < 100 group by c2;
 | |
|                                          QUERY PLAN                                         
 | |
| --------------------------------------------------------------------------------------------
 | |
|  GroupAggregate
 | |
|    Output: array_agg(c1 ORDER BY c1 USING <^ NULLS LAST), c2
 | |
|    Group Key: ft2.c2
 | |
|    ->  Foreign Scan on public.ft2
 | |
|          Output: c2, c1
 | |
|          Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE (("C 1" < 100)) AND ((c2 = 6))
 | |
| (6 rows)
 | |
| 
 | |
| -- Cleanup
 | |
| drop operator class my_op_class using btree;
 | |
| drop function my_op_cmp(a int, b int);
 | |
| drop operator family my_op_family using btree;
 | |
| drop operator public.>^(int, int);
 | |
| drop operator public.=^(int, int);
 | |
| drop operator public.<^(int, int);
 | |
| -- Input relation to aggregate push down hook is not safe to pushdown and thus
 | |
| -- the aggregate cannot be pushed down to foreign server.
 | |
| explain (verbose, costs off)
 | |
| select count(t1.c3) from ft1 t1, ft1 t2 where t1.c1 = postgres_fdw_abs(t1.c2);
 | |
|                                                 QUERY PLAN                                                
 | |
| ----------------------------------------------------------------------------------------------------------
 | |
|  Aggregate
 | |
|    Output: count(t1.c3)
 | |
|    ->  Nested Loop
 | |
|          Output: t1.c3
 | |
|          ->  Foreign Scan on public.ft1 t2
 | |
|                Remote SQL: SELECT NULL FROM "S 1"."T 1"
 | |
|          ->  Materialize
 | |
|                Output: t1.c3
 | |
|                ->  Foreign Scan on public.ft1 t1
 | |
|                      Output: t1.c3
 | |
|                      Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" = public.postgres_fdw_abs(c2)))
 | |
| (11 rows)
 | |
| 
 | |
| -- Subquery in FROM clause having aggregate
 | |
| explain (verbose, costs off)
 | |
| select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2;
 | |
|                                            QUERY PLAN                                           
 | |
| ------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (count(*)), x.b
 | |
|    Sort Key: (count(*)), x.b
 | |
|    ->  HashAggregate
 | |
|          Output: count(*), x.b
 | |
|          Group Key: x.b
 | |
|          ->  Hash Join
 | |
|                Output: x.b
 | |
|                Hash Cond: (ft1.c2 = x.a)
 | |
|                ->  Foreign Scan on public.ft1
 | |
|                      Output: ft1.c2
 | |
|                      Remote SQL: SELECT c2 FROM "S 1"."T 1"
 | |
|                ->  Hash
 | |
|                      Output: x.b, x.a
 | |
|                      ->  Subquery Scan on x
 | |
|                            Output: x.b, x.a
 | |
|                            ->  Foreign Scan
 | |
|                                  Output: ft1_1.c2, (sum(ft1_1.c1))
 | |
|                                  Relations: Aggregate on (public.ft1)
 | |
|                                  Remote SQL: SELECT c2, sum("C 1") FROM "S 1"."T 1" GROUP BY c2
 | |
| (20 rows)
 | |
| 
 | |
| select count(*), x.b from ft1, (select c2 a, sum(c1) b from ft1 group by c2) x where ft1.c2 = x.a group by x.b order by 1, 2;
 | |
|  count |   b   
 | |
| -------+-------
 | |
|    100 | 49600
 | |
|    100 | 49700
 | |
|    100 | 49800
 | |
|    100 | 49900
 | |
|    100 | 50000
 | |
|    100 | 50100
 | |
|    100 | 50200
 | |
|    100 | 50300
 | |
|    100 | 50400
 | |
|    100 | 50500
 | |
| (10 rows)
 | |
| 
 | |
| -- FULL join with IS NULL check in HAVING
 | |
| explain (verbose, costs off)
 | |
| select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2;
 | |
|                                                                                                           QUERY PLAN                                                                                                           
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1
 | |
|    Sort Key: (avg(t1.c1)), (sum(t2.c1))
 | |
|    ->  Foreign Scan
 | |
|          Output: (avg(t1.c1)), (sum(t2.c1)), t2.c1
 | |
|          Relations: Aggregate on ((public.ft4 t1) FULL JOIN (public.ft5 t2))
 | |
|          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 r2.c1 HAVING ((((avg(r1.c1) IS NULL) AND (sum(r2.c1) < 10)) OR (sum(r2.c1) IS NULL)))
 | |
| (7 rows)
 | |
| 
 | |
| select avg(t1.c1), sum(t2.c1) from ft4 t1 full join ft5 t2 on (t1.c1 = t2.c1) group by t2.c1 having (avg(t1.c1) is null and sum(t2.c1) < 10) or sum(t2.c1) is null order by 1 nulls last, 2;
 | |
|          avg         | sum 
 | |
| ---------------------+-----
 | |
|  51.0000000000000000 |    
 | |
|                      |   3
 | |
|                      |   9
 | |
| (3 rows)
 | |
| 
 | |
| -- ORDER BY expression is part of the target list but not pushed down to
 | |
| -- foreign server.
 | |
| explain (verbose, costs off)
 | |
| select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1;
 | |
|                                    QUERY PLAN                                   
 | |
| --------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: (((sum(c2)) * ((random() <= '1'::double precision))::integer))
 | |
|    Sort Key: (((sum(ft1.c2)) * ((random() <= '1'::double precision))::integer))
 | |
|    ->  Foreign Scan
 | |
|          Output: ((sum(c2)) * ((random() <= '1'::double precision))::integer)
 | |
|          Relations: Aggregate on (public.ft1)
 | |
|          Remote SQL: SELECT sum(c2) FROM "S 1"."T 1"
 | |
| (7 rows)
 | |
| 
 | |
| select sum(c2) * (random() <= 1)::int as sum from ft1 order by 1;
 | |
|  sum  
 | |
| ------
 | |
|  4500
 | |
| (1 row)
 | |
| 
 | |
| -- LATERAL join, with parameterization
 | |
| set enable_hashagg to false;
 | |
| explain (verbose, costs off)
 | |
| select c2, sum from "S 1"."T 1" t1, lateral (select sum(t2.c1 + t1."C 1") sum from ft2 t2 group by t2.c1) qry where t1.c2 * 2 = qry.sum and t1.c2 < 10 order by 1;
 | |
|                                                 QUERY PLAN                                                
 | |
| ----------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: t1.c2, qry.sum
 | |
|    Sort Key: t1.c2
 | |
|    ->  Nested Loop
 | |
|          Output: t1.c2, qry.sum
 | |
|          ->  Seq Scan on "S 1"."T 1" t1
 | |
|                Output: t1."C 1", t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
 | |
|                Filter: (t1.c2 < 10)
 | |
|          ->  Subquery Scan on qry
 | |
|                Output: qry.sum, t2.c1
 | |
|                Filter: ((t1.c2 * 2) = qry.sum)
 | |
|                ->  Foreign Scan
 | |
|                      Output: (sum((t2.c1 + t1."C 1"))), t2.c1
 | |
|                      Relations: Aggregate on (public.ft2 t2)
 | |
|                      Remote SQL: SELECT sum(("C 1" + $1::integer)), "C 1" FROM "S 1"."T 1" GROUP BY "C 1"
 | |
| (15 rows)
 | |
| 
 | |
| 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 < 10 order by 1;
 | |
|  c2 | sum 
 | |
| ----+-----
 | |
|   1 |   2
 | |
|   2 |   4
 | |
|   3 |   6
 | |
|   4 |   8
 | |
|   5 |  10
 | |
|   6 |  12
 | |
|   7 |  14
 | |
|   8 |  16
 | |
|   9 |  18
 | |
| (9 rows)
 | |
| 
 | |
| reset enable_hashagg;
 | |
| -- Check with placeHolderVars
 | |
| explain (verbose, costs off)
 | |
| select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b);
 | |
|                                                                         QUERY PLAN                                                                        
 | |
| ----------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Aggregate
 | |
|    Output: sum(q.a), count(q.b)
 | |
|    ->  Nested Loop Left Join
 | |
|          Output: q.a, q.b
 | |
|          Join Filter: ((ft4.c1)::numeric <= q.b)
 | |
|          ->  Foreign Scan on public.ft4
 | |
|                Output: ft4.c1, ft4.c2, ft4.c3
 | |
|                Remote SQL: SELECT c1 FROM "S 1"."T 3"
 | |
|          ->  Materialize
 | |
|                Output: q.a, q.b
 | |
|                ->  Subquery Scan on q
 | |
|                      Output: q.a, q.b
 | |
|                      ->  Foreign Scan
 | |
|                            Output: 13, (avg(ft1.c1)), NULL::bigint
 | |
|                            Relations: Aggregate on ((public.ft2) LEFT JOIN (public.ft1))
 | |
|                            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"))))
 | |
| (16 rows)
 | |
| 
 | |
| select sum(q.a), count(q.b) from ft4 left join (select 13, avg(ft1.c1), sum(ft2.c1) from ft1 right join ft2 on (ft1.c1 = ft2.c1)) q(a, b, c) on (ft4.c1 <= q.b);
 | |
|  sum | count 
 | |
| -----+-------
 | |
|  650 |    50
 | |
| (1 row)
 | |
| 
 | |
| -- Not supported cases
 | |
| -- Grouping sets
 | |
| explain (verbose, costs off)
 | |
| select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last;
 | |
|                                             QUERY PLAN                                             
 | |
| ---------------------------------------------------------------------------------------------------
 | |
|  GroupAggregate
 | |
|    Output: c2, sum(c1)
 | |
|    Group Key: ft1.c2
 | |
|    Group Key: ()
 | |
|    ->  Foreign Scan on public.ft1
 | |
|          Output: c2, c1
 | |
|          Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3)) ORDER BY c2 ASC NULLS LAST
 | |
| (7 rows)
 | |
| 
 | |
| select c2, sum(c1) from ft1 where c2 < 3 group by rollup(c2) order by 1 nulls last;
 | |
|  c2 |  sum   
 | |
| ----+--------
 | |
|   0 |  50500
 | |
|   1 |  49600
 | |
|   2 |  49700
 | |
|     | 149800
 | |
| (4 rows)
 | |
| 
 | |
| explain (verbose, costs off)
 | |
| select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last;
 | |
|                                             QUERY PLAN                                             
 | |
| ---------------------------------------------------------------------------------------------------
 | |
|  GroupAggregate
 | |
|    Output: c2, sum(c1)
 | |
|    Group Key: ft1.c2
 | |
|    Group Key: ()
 | |
|    ->  Foreign Scan on public.ft1
 | |
|          Output: c2, c1
 | |
|          Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3)) ORDER BY c2 ASC NULLS LAST
 | |
| (7 rows)
 | |
| 
 | |
| select c2, sum(c1) from ft1 where c2 < 3 group by cube(c2) order by 1 nulls last;
 | |
|  c2 |  sum   
 | |
| ----+--------
 | |
|   0 |  50500
 | |
|   1 |  49600
 | |
|   2 |  49700
 | |
|     | 149800
 | |
| (4 rows)
 | |
| 
 | |
| explain (verbose, costs off)
 | |
| select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last;
 | |
|                                                  QUERY PLAN                                                  
 | |
| -------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: c2, c6, (sum(c1))
 | |
|    Sort Key: ft1.c2, ft1.c6
 | |
|    ->  GroupAggregate
 | |
|          Output: c2, c6, sum(c1)
 | |
|          Group Key: ft1.c2
 | |
|          Sort Key: ft1.c6
 | |
|            Group Key: ft1.c6
 | |
|          ->  Foreign Scan on public.ft1
 | |
|                Output: c2, c6, c1
 | |
|                Remote SQL: SELECT "C 1", c2, c6 FROM "S 1"."T 1" WHERE ((c2 < 3)) ORDER BY c2 ASC NULLS LAST
 | |
| (11 rows)
 | |
| 
 | |
| select c2, c6, sum(c1) from ft1 where c2 < 3 group by grouping sets(c2, c6) order by 1 nulls last, 2 nulls last;
 | |
|  c2 | c6 |  sum  
 | |
| ----+----+-------
 | |
|   0 |    | 50500
 | |
|   1 |    | 49600
 | |
|   2 |    | 49700
 | |
|     | 0  | 50500
 | |
|     | 1  | 49600
 | |
|     | 2  | 49700
 | |
| (6 rows)
 | |
| 
 | |
| explain (verbose, costs off)
 | |
| select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last;
 | |
|                                   QUERY PLAN                                  
 | |
| ------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: c2, (sum(c1)), (GROUPING(c2))
 | |
|    Sort Key: ft1.c2
 | |
|    ->  HashAggregate
 | |
|          Output: c2, sum(c1), GROUPING(c2)
 | |
|          Group Key: ft1.c2
 | |
|          ->  Foreign Scan on public.ft1
 | |
|                Output: c2, c1
 | |
|                Remote SQL: SELECT "C 1", c2 FROM "S 1"."T 1" WHERE ((c2 < 3))
 | |
| (9 rows)
 | |
| 
 | |
| select c2, sum(c1), grouping(c2) from ft1 where c2 < 3 group by c2 order by 1 nulls last;
 | |
|  c2 |  sum  | grouping 
 | |
| ----+-------+----------
 | |
|   0 | 50500 |        0
 | |
|   1 | 49600 |        0
 | |
|   2 | 49700 |        0
 | |
| (3 rows)
 | |
| 
 | |
| -- DISTINCT itself is not pushed down, whereas underneath aggregate is pushed
 | |
| explain (verbose, costs off)
 | |
| select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1;
 | |
|                                                QUERY PLAN                                               
 | |
| --------------------------------------------------------------------------------------------------------
 | |
|  Unique
 | |
|    Output: ((sum(c1) / 1000)), c2
 | |
|    ->  Sort
 | |
|          Output: ((sum(c1) / 1000)), c2
 | |
|          Sort Key: ((sum(ft2.c1) / 1000))
 | |
|          ->  Foreign Scan
 | |
|                Output: ((sum(c1) / 1000)), c2
 | |
|                Relations: Aggregate on (public.ft2)
 | |
|                Remote SQL: SELECT (sum("C 1") / 1000), c2 FROM "S 1"."T 1" WHERE ((c2 < 6)) GROUP BY c2
 | |
| (9 rows)
 | |
| 
 | |
| select distinct sum(c1)/1000 s from ft2 where c2 < 6 group by c2 order by 1;
 | |
|  s  
 | |
| ----
 | |
|  49
 | |
|  50
 | |
| (2 rows)
 | |
| 
 | |
| -- WindowAgg
 | |
| explain (verbose, costs off)
 | |
| select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1;
 | |
|                                                  QUERY PLAN                                                  
 | |
| -------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: c2, (sum(c2)), (count(c2) OVER (?)), ((c2 % 2))
 | |
|    Sort Key: ft2.c2
 | |
|    ->  WindowAgg
 | |
|          Output: c2, (sum(c2)), count(c2) OVER (?), ((c2 % 2))
 | |
|          ->  Sort
 | |
|                Output: c2, ((c2 % 2)), (sum(c2))
 | |
|                Sort Key: ((ft2.c2 % 2))
 | |
|                ->  Foreign Scan
 | |
|                      Output: c2, ((c2 % 2)), (sum(c2))
 | |
|                      Relations: Aggregate on (public.ft2)
 | |
|                      Remote SQL: SELECT c2, (c2 % 2), sum(c2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY c2
 | |
| (12 rows)
 | |
| 
 | |
| select c2, sum(c2), count(c2) over (partition by c2%2) from ft2 where c2 < 10 group by c2 order by 1;
 | |
|  c2 | sum | count 
 | |
| ----+-----+-------
 | |
|   0 |   0 |     5
 | |
|   1 | 100 |     5
 | |
|   2 | 200 |     5
 | |
|   3 | 300 |     5
 | |
|   4 | 400 |     5
 | |
|   5 | 500 |     5
 | |
|   6 | 600 |     5
 | |
|   7 | 700 |     5
 | |
|   8 | 800 |     5
 | |
|   9 | 900 |     5
 | |
| (10 rows)
 | |
| 
 | |
| explain (verbose, costs off)
 | |
| select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1;
 | |
|                                              QUERY PLAN                                             
 | |
| ----------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2))
 | |
|    Sort Key: ft1.c2
 | |
|    ->  WindowAgg
 | |
|          Output: c2, array_agg(c2) OVER (?), ((c2 % 2))
 | |
|          ->  Sort
 | |
|                Output: c2, ((c2 % 2))
 | |
|                Sort Key: ((ft1.c2 % 2)), ft1.c2 DESC
 | |
|                ->  Foreign Scan
 | |
|                      Output: c2, ((c2 % 2))
 | |
|                      Relations: Aggregate on (public.ft1)
 | |
|                      Remote SQL: SELECT c2, (c2 % 2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY c2
 | |
| (12 rows)
 | |
| 
 | |
| select c2, array_agg(c2) over (partition by c2%2 order by c2 desc) from ft1 where c2 < 10 group by c2 order by 1;
 | |
|  c2 |  array_agg  
 | |
| ----+-------------
 | |
|   0 | {8,6,4,2,0}
 | |
|   1 | {9,7,5,3,1}
 | |
|   2 | {8,6,4,2}
 | |
|   3 | {9,7,5,3}
 | |
|   4 | {8,6,4}
 | |
|   5 | {9,7,5}
 | |
|   6 | {8,6}
 | |
|   7 | {9,7}
 | |
|   8 | {8}
 | |
|   9 | {9}
 | |
| (10 rows)
 | |
| 
 | |
| explain (verbose, costs off)
 | |
| select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1;
 | |
|                                              QUERY PLAN                                             
 | |
| ----------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: c2, (array_agg(c2) OVER (?)), ((c2 % 2))
 | |
|    Sort Key: ft1.c2
 | |
|    ->  WindowAgg
 | |
|          Output: c2, array_agg(c2) OVER (?), ((c2 % 2))
 | |
|          ->  Sort
 | |
|                Output: c2, ((c2 % 2))
 | |
|                Sort Key: ((ft1.c2 % 2)), ft1.c2
 | |
|                ->  Foreign Scan
 | |
|                      Output: c2, ((c2 % 2))
 | |
|                      Relations: Aggregate on (public.ft1)
 | |
|                      Remote SQL: SELECT c2, (c2 % 2) FROM "S 1"."T 1" WHERE ((c2 < 10)) GROUP BY c2
 | |
| (12 rows)
 | |
| 
 | |
| select c2, array_agg(c2) over (partition by c2%2 order by c2 range between current row and unbounded following) from ft1 where c2 < 10 group by c2 order by 1;
 | |
|  c2 |  array_agg  
 | |
| ----+-------------
 | |
|   0 | {0,2,4,6,8}
 | |
|   1 | {1,3,5,7,9}
 | |
|   2 | {2,4,6,8}
 | |
|   3 | {3,5,7,9}
 | |
|   4 | {4,6,8}
 | |
|   5 | {5,7,9}
 | |
|   6 | {6,8}
 | |
|   7 | {7,9}
 | |
|   8 | {8}
 | |
|   9 | {9}
 | |
| (10 rows)
 | |
| 
 | |
| -- ===================================================================
 | |
| -- parameterized queries
 | |
| -- ===================================================================
 | |
| -- simple join
 | |
| PREPARE st1(int, int) AS SELECT t1.c3, t2.c3 FROM ft1 t1, ft2 t2 WHERE t1.c1 = $1 AND t2.c1 = $2;
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st1(1, 2);
 | |
|                                                           QUERY PLAN                                                          
 | |
| ------------------------------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: t1.c3, t2.c3
 | |
|    Relations: (public.ft1 t1) INNER JOIN (public.ft2 t2)
 | |
|    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))))
 | |
| (4 rows)
 | |
| 
 | |
| EXECUTE st1(1, 1);
 | |
|   c3   |  c3   
 | |
| -------+-------
 | |
|  00001 | 00001
 | |
| (1 row)
 | |
| 
 | |
| EXECUTE st1(101, 101);
 | |
|   c3   |  c3   
 | |
| -------+-------
 | |
|  00101 | 00101
 | |
| (1 row)
 | |
| 
 | |
| -- subquery using stable function (can't be sent to remote)
 | |
| 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;
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st2(10, 20);
 | |
|                                                 QUERY PLAN                                                
 | |
| ----------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
 | |
|    Sort Key: t1.c1
 | |
|    ->  Nested Loop Semi Join
 | |
|          Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
 | |
|          Join Filter: (t1.c3 = t2.c3)
 | |
|          ->  Foreign Scan on public.ft1 t1
 | |
|                Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
 | |
|                Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 20))
 | |
|          ->  Materialize
 | |
|                Output: t2.c3
 | |
|                ->  Foreign Scan on public.ft2 t2
 | |
|                      Output: t2.c3
 | |
|                      Filter: (date(t2.c4) = '01-17-1970'::date)
 | |
|                      Remote SQL: SELECT c3, c4 FROM "S 1"."T 1" WHERE (("C 1" > 10))
 | |
| (15 rows)
 | |
| 
 | |
| EXECUTE st2(10, 20);
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  16 |  6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
| (1 row)
 | |
| 
 | |
| EXECUTE st2(101, 121);
 | |
|  c1  | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| -----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  116 |  6 | 00116 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
| (1 row)
 | |
| 
 | |
| -- subquery using immutable function (can be sent to remote)
 | |
| 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;
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st3(10, 20);
 | |
|                                                       QUERY PLAN                                                       
 | |
| -----------------------------------------------------------------------------------------------------------------------
 | |
|  Sort
 | |
|    Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
 | |
|    Sort Key: t1.c1
 | |
|    ->  Nested Loop Semi Join
 | |
|          Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
 | |
|          Join Filter: (t1.c3 = t2.c3)
 | |
|          ->  Foreign Scan on public.ft1 t1
 | |
|                Output: t1.c1, t1.c2, t1.c3, t1.c4, t1.c5, t1.c6, t1.c7, t1.c8
 | |
|                Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" < 20))
 | |
|          ->  Materialize
 | |
|                Output: t2.c3
 | |
|                ->  Foreign Scan on public.ft2 t2
 | |
|                      Output: t2.c3
 | |
|                      Remote SQL: SELECT c3 FROM "S 1"."T 1" WHERE (("C 1" > 10)) AND ((date(c5) = '1970-01-17'::date))
 | |
| (14 rows)
 | |
| 
 | |
| EXECUTE st3(10, 20);
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  16 |  6 | 00016 | Sat Jan 17 00:00:00 1970 PST | Sat Jan 17 00:00:00 1970 | 6  | 6          | foo
 | |
| (1 row)
 | |
| 
 | |
| EXECUTE st3(20, 30);
 | |
|  c1 | c2 | c3 | c4 | c5 | c6 | c7 | c8 
 | |
| ----+----+----+----+----+----+----+----
 | |
| (0 rows)
 | |
| 
 | |
| -- custom plan should be chosen initially
 | |
| PREPARE st4(int) AS SELECT * FROM ft1 t1 WHERE t1.c1 = $1;
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (3 rows)
 | |
| 
 | |
| -- once we try it enough times, should switch to generic plan
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st4(1);
 | |
|                                               QUERY PLAN                                               
 | |
| -------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
 | |
| (3 rows)
 | |
| 
 | |
| -- value of $1 should not be sent to remote
 | |
| PREPARE st5(user_enum,int) AS SELECT * FROM ft1 t1 WHERE c8 = $1 and c1 = $2;
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Filter: (t1.c8 = 'foo'::user_enum)
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (4 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Filter: (t1.c8 = 'foo'::user_enum)
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (4 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Filter: (t1.c8 = 'foo'::user_enum)
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (4 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Filter: (t1.c8 = 'foo'::user_enum)
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (4 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Filter: (t1.c8 = 'foo'::user_enum)
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = 1))
 | |
| (4 rows)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF) EXECUTE st5('foo', 1);
 | |
|                                               QUERY PLAN                                               
 | |
| -------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Filter: (t1.c8 = $1)
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE (("C 1" = $1::integer))
 | |
| (4 rows)
 | |
| 
 | |
| EXECUTE st5('foo', 1);
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
| (1 row)
 | |
| 
 | |
| -- cleanup
 | |
| DEALLOCATE st1;
 | |
| DEALLOCATE st2;
 | |
| DEALLOCATE st3;
 | |
| DEALLOCATE st4;
 | |
| DEALLOCATE st5;
 | |
| -- System columns, except ctid and oid, should not be sent to remote
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT * FROM ft1 t1 WHERE t1.tableoid = 'pg_class'::regclass LIMIT 1;
 | |
|                                   QUERY PLAN                                   
 | |
| -------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    ->  Foreign Scan on public.ft1 t1
 | |
|          Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|          Filter: (t1.tableoid = '1259'::oid)
 | |
|          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
 | |
| (6 rows)
 | |
| 
 | |
| SELECT * FROM ft1 t1 WHERE t1.tableoid = 'ft1'::regclass LIMIT 1;
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
| (1 row)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1;
 | |
|                                   QUERY PLAN                                   
 | |
| -------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: ((tableoid)::regclass), c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    ->  Foreign Scan on public.ft1 t1
 | |
|          Output: (tableoid)::regclass, c1, c2, c3, c4, c5, c6, c7, c8
 | |
|          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1"
 | |
| (5 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM ft1 t1 LIMIT 1;
 | |
|  tableoid | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----------+----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  ft1      |  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
| (1 row)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)';
 | |
|                                               QUERY PLAN                                               
 | |
| -------------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft1 t1
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((ctid = '(0,2)'::tid))
 | |
| (3 rows)
 | |
| 
 | |
| SELECT * FROM ft1 t1 WHERE t1.ctid = '(0,2)';
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
 | |
| (1 row)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT ctid, * FROM ft1 t1 LIMIT 1;
 | |
|                                      QUERY PLAN                                      
 | |
| -------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    ->  Foreign Scan on public.ft1 t1
 | |
|          Output: ctid, c1, c2, c3, c4, c5, c6, c7, c8
 | |
|          Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8, ctid FROM "S 1"."T 1"
 | |
| (5 rows)
 | |
| 
 | |
| SELECT ctid, * FROM ft1 t1 LIMIT 1;
 | |
|  ctid  | c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| -------+----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|  (0,1) |  1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
| (1 row)
 | |
| 
 | |
| EXPLAIN (VERBOSE, COSTS OFF)
 | |
| SELECT oid, * FROM ft_pg_type WHERE typname = 'int4';
 | |
|                                              QUERY PLAN                                             
 | |
| ----------------------------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft_pg_type
 | |
|    Output: oid, typname, typlen
 | |
|    Remote SQL: SELECT typname, typlen, oid FROM pg_catalog.pg_type WHERE ((typname = 'int4'::name))
 | |
| (3 rows)
 | |
| 
 | |
| SELECT oid, * FROM ft_pg_type WHERE typname = 'int4';
 | |
|  oid | typname | typlen 
 | |
| -----+---------+--------
 | |
|   23 | int4    |      4
 | |
| (1 row)
 | |
| 
 | |
| -- ===================================================================
 | |
| -- used in pl/pgsql function
 | |
| -- ===================================================================
 | |
| CREATE OR REPLACE FUNCTION f_test(p_c1 int) RETURNS int AS $$
 | |
| DECLARE
 | |
| 	v_c1 int;
 | |
| BEGIN
 | |
|     SELECT c1 INTO v_c1 FROM ft1 WHERE c1 = p_c1 LIMIT 1;
 | |
|     PERFORM c1 FROM ft1 WHERE c1 = p_c1 AND p_c1 = v_c1 LIMIT 1;
 | |
|     RETURN v_c1;
 | |
| END;
 | |
| $$ LANGUAGE plpgsql;
 | |
| SELECT f_test(100);
 | |
|  f_test 
 | |
| --------
 | |
|     100
 | |
| (1 row)
 | |
| 
 | |
| DROP FUNCTION f_test(int);
 | |
| -- ===================================================================
 | |
| -- conversion error
 | |
| -- ===================================================================
 | |
| ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE int;
 | |
| SELECT * FROM ft1 WHERE c1 = 1;  -- ERROR
 | |
| ERROR:  invalid input syntax for integer: "foo"
 | |
| CONTEXT:  column "c8" of foreign table "ft1"
 | |
| SELECT  ft1.c1,  ft2.c2, ft1.c8 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; -- ERROR
 | |
| ERROR:  invalid input syntax for integer: "foo"
 | |
| CONTEXT:  column "c8" of foreign table "ft1"
 | |
| SELECT  ft1.c1,  ft2.c2, ft1 FROM ft1, ft2 WHERE ft1.c1 = ft2.c1 AND ft1.c1 = 1; -- ERROR
 | |
| ERROR:  invalid input syntax for integer: "foo"
 | |
| CONTEXT:  whole-row reference to foreign table "ft1"
 | |
| SELECT sum(c2), array_agg(c8) FROM ft1 GROUP BY c8; -- ERROR
 | |
| ERROR:  invalid input syntax for integer: "foo"
 | |
| CONTEXT:  processing expression at position 2 in select list
 | |
| ALTER FOREIGN TABLE ft1 ALTER COLUMN c8 TYPE user_enum;
 | |
| -- ===================================================================
 | |
| -- subtransaction
 | |
| --  + local/remote error doesn't break cursor
 | |
| -- ===================================================================
 | |
| BEGIN;
 | |
| DECLARE c CURSOR FOR SELECT * FROM ft1 ORDER BY c1;
 | |
| FETCH c;
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
| (1 row)
 | |
| 
 | |
| SAVEPOINT s;
 | |
| ERROR OUT;          -- ERROR
 | |
| ERROR:  syntax error at or near "ERROR"
 | |
| LINE 1: ERROR OUT;
 | |
|         ^
 | |
| ROLLBACK TO s;
 | |
| FETCH c;
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|   2 |  2 | 00002 | Sat Jan 03 00:00:00 1970 PST | Sat Jan 03 00:00:00 1970 | 2  | 2          | foo
 | |
| (1 row)
 | |
| 
 | |
| SAVEPOINT s;
 | |
| SELECT * FROM ft1 WHERE 1 / (c1 - 1) > 0;  -- ERROR
 | |
| ERROR:  division by zero
 | |
| 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))
 | |
| ROLLBACK TO s;
 | |
| FETCH c;
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|   3 |  3 | 00003 | Sun Jan 04 00:00:00 1970 PST | Sun Jan 04 00:00:00 1970 | 3  | 3          | foo
 | |
| (1 row)
 | |
| 
 | |
| SELECT * FROM ft1 ORDER BY c1 LIMIT 1;
 | |
|  c1 | c2 |  c3   |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ----+----+-------+------------------------------+--------------------------+----+------------+-----
 | |
|   1 |  1 | 00001 | Fri Jan 02 00:00:00 1970 PST | Fri Jan 02 00:00:00 1970 | 1  | 1          | foo
 | |
| (1 row)
 | |
| 
 | |
| COMMIT;
 | |
| -- ===================================================================
 | |
| -- test handling of collations
 | |
| -- ===================================================================
 | |
| create table loct3 (f1 text collate "C" unique, f2 text, f3 varchar(10) unique);
 | |
| create foreign table ft3 (f1 text collate "C", f2 text, f3 varchar(10))
 | |
|   server loopback options (table_name 'loct3', use_remote_estimate 'true');
 | |
| -- can be sent to remote
 | |
| explain (verbose, costs off) select * from ft3 where f1 = 'foo';
 | |
|                                   QUERY PLAN                                  
 | |
| ------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft3
 | |
|    Output: f1, f2, f3
 | |
|    Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f1 = 'foo'::text))
 | |
| (3 rows)
 | |
| 
 | |
| explain (verbose, costs off) select * from ft3 where f1 COLLATE "C" = 'foo';
 | |
|                                   QUERY PLAN                                  
 | |
| ------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft3
 | |
|    Output: f1, f2, f3
 | |
|    Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f1 = 'foo'::text))
 | |
| (3 rows)
 | |
| 
 | |
| explain (verbose, costs off) select * from ft3 where f2 = 'foo';
 | |
|                                   QUERY PLAN                                  
 | |
| ------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft3
 | |
|    Output: f1, f2, f3
 | |
|    Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f2 = 'foo'::text))
 | |
| (3 rows)
 | |
| 
 | |
| explain (verbose, costs off) select * from ft3 where f3 = 'foo';
 | |
|                                   QUERY PLAN                                  
 | |
| ------------------------------------------------------------------------------
 | |
|  Foreign Scan on public.ft3
 | |
|    Output: f1, f2, f3
 | |
|    Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE ((f3 = 'foo'::text))
 | |
| (3 rows)
 | |
| 
 | |
| explain (verbose, costs off) select * from ft3 f, loct3 l
 | |
|   where f.f3 = l.f3 and l.f1 = 'foo';
 | |
|                                             QUERY PLAN                                            
 | |
| --------------------------------------------------------------------------------------------------
 | |
|  Nested Loop
 | |
|    Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
 | |
|    ->  Index Scan using loct3_f1_key on public.loct3 l
 | |
|          Output: l.f1, l.f2, l.f3
 | |
|          Index Cond: (l.f1 = 'foo'::text)
 | |
|    ->  Foreign Scan on public.ft3 f
 | |
|          Output: f.f1, f.f2, f.f3
 | |
|          Remote SQL: SELECT f1, f2, f3 FROM public.loct3 WHERE (($1::character varying(10) = f3))
 | |
| (8 rows)
 | |
| 
 | |
| -- can't be sent to remote
 | |
| explain (verbose, costs off) select * from ft3 where f1 COLLATE "POSIX" = 'foo';
 | |
|                     QUERY PLAN                     
 | |
| ---------------------------------------------------
 | |
|  Foreign Scan on public.ft3
 | |
|    Output: f1, f2, f3
 | |
|    Filter: ((ft3.f1)::text = 'foo'::text)
 | |
|    Remote SQL: SELECT f1, f2, f3 FROM public.loct3
 | |
| (4 rows)
 | |
| 
 | |
| explain (verbose, costs off) select * from ft3 where f1 = 'foo' COLLATE "C";
 | |
|                     QUERY PLAN                     
 | |
| ---------------------------------------------------
 | |
|  Foreign Scan on public.ft3
 | |
|    Output: f1, f2, f3
 | |
|    Filter: (ft3.f1 = 'foo'::text COLLATE "C")
 | |
|    Remote SQL: SELECT f1, f2, f3 FROM public.loct3
 | |
| (4 rows)
 | |
| 
 | |
| explain (verbose, costs off) select * from ft3 where f2 COLLATE "C" = 'foo';
 | |
|                     QUERY PLAN                     
 | |
| ---------------------------------------------------
 | |
|  Foreign Scan on public.ft3
 | |
|    Output: f1, f2, f3
 | |
|    Filter: ((ft3.f2)::text = 'foo'::text)
 | |
|    Remote SQL: SELECT f1, f2, f3 FROM public.loct3
 | |
| (4 rows)
 | |
| 
 | |
| explain (verbose, costs off) select * from ft3 where f2 = 'foo' COLLATE "C";
 | |
|                     QUERY PLAN                     
 | |
| ---------------------------------------------------
 | |
|  Foreign Scan on public.ft3
 | |
|    Output: f1, f2, f3
 | |
|    Filter: (ft3.f2 = 'foo'::text COLLATE "C")
 | |
|    Remote SQL: SELECT f1, f2, f3 FROM public.loct3
 | |
| (4 rows)
 | |
| 
 | |
| explain (verbose, costs off) select * from ft3 f, loct3 l
 | |
|   where f.f3 = l.f3 COLLATE "POSIX" and l.f1 = 'foo';
 | |
|                          QUERY PLAN                          
 | |
| -------------------------------------------------------------
 | |
|  Hash Join
 | |
|    Output: f.f1, f.f2, f.f3, l.f1, l.f2, l.f3
 | |
|    Hash Cond: ((f.f3)::text = (l.f3)::text)
 | |
|    ->  Foreign Scan on public.ft3 f
 | |
|          Output: f.f1, f.f2, f.f3
 | |
|          Remote SQL: SELECT f1, f2, f3 FROM public.loct3
 | |
|    ->  Hash
 | |
|          Output: l.f1, l.f2, l.f3
 | |
|          ->  Index Scan using loct3_f1_key on public.loct3 l
 | |
|                Output: l.f1, l.f2, l.f3
 | |
|                Index Cond: (l.f1 = 'foo'::text)
 | |
| (11 rows)
 | |
| 
 | |
| -- ===================================================================
 | |
| -- test writable foreign table stuff
 | |
| -- ===================================================================
 | |
| EXPLAIN (verbose, costs off)
 | |
| INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
 | |
|                                                                                                                     QUERY PLAN                                                                                                                    
 | |
| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Insert on public.ft2
 | |
|    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)
 | |
|    ->  Subquery Scan on "*SELECT*"
 | |
|          Output: "*SELECT*"."?column?", "*SELECT*"."?column?_1", NULL::integer, "*SELECT*"."?column?_2", NULL::timestamp with time zone, NULL::timestamp without time zone, NULL::character varying, 'ft2       '::character(10), NULL::user_enum
 | |
|          ->  Limit
 | |
|                Output: ((ft2_1.c1 + 1000)), ((ft2_1.c2 + 100)), ((ft2_1.c3 || ft2_1.c3))
 | |
|                ->  Foreign Scan on public.ft2 ft2_1
 | |
|                      Output: (ft2_1.c1 + 1000), (ft2_1.c2 + 100), (ft2_1.c3 || ft2_1.c3)
 | |
|                      Remote SQL: SELECT "C 1", c2, c3 FROM "S 1"."T 1"
 | |
| (9 rows)
 | |
| 
 | |
| INSERT INTO ft2 (c1,c2,c3) SELECT c1+1000,c2+100, c3 || c3 FROM ft2 LIMIT 20;
 | |
| INSERT INTO ft2 (c1,c2,c3)
 | |
|   VALUES (1101,201,'aaa'), (1102,202,'bbb'), (1103,203,'ccc') RETURNING *;
 | |
|   c1  | c2  | c3  | c4 | c5 | c6 |     c7     | c8 
 | |
| ------+-----+-----+----+----+----+------------+----
 | |
|  1101 | 201 | aaa |    |    |    | ft2        | 
 | |
|  1102 | 202 | bbb |    |    |    | ft2        | 
 | |
|  1103 | 203 | ccc |    |    |    | ft2        | 
 | |
| (3 rows)
 | |
| 
 | |
| INSERT INTO ft2 (c1,c2,c3) VALUES (1104,204,'ddd'), (1105,205,'eee');
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3;              -- can be pushed down
 | |
|                                                       QUERY PLAN                                                      
 | |
| ----------------------------------------------------------------------------------------------------------------------
 | |
|  Update on public.ft2
 | |
|    ->  Foreign Update on public.ft2
 | |
|          Remote SQL: UPDATE "S 1"."T 1" SET c2 = (c2 + 300), c3 = (c3 || '_update3'::text) WHERE ((("C 1" % 10) = 3))
 | |
| (3 rows)
 | |
| 
 | |
| UPDATE ft2 SET c2 = c2 + 300, c3 = c3 || '_update3' WHERE c1 % 10 = 3;
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *;  -- can be pushed down
 | |
|                                                                             QUERY PLAN                                                                            
 | |
| ------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Update on public.ft2
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    ->  Foreign Update on public.ft2
 | |
|          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
 | |
| (4 rows)
 | |
| 
 | |
| UPDATE ft2 SET c2 = c2 + 400, c3 = c3 || '_update7' WHERE c1 % 10 = 7 RETURNING *;
 | |
|   c1  | c2  |         c3         |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ------+-----+--------------------+------------------------------+--------------------------+----+------------+-----
 | |
|     7 | 407 | 00007_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|    17 | 407 | 00017_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
 | |
|    27 | 407 | 00027_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
 | |
|    37 | 407 | 00037_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
 | |
|    47 | 407 | 00047_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
 | |
|    57 | 407 | 00057_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
 | |
|    67 | 407 | 00067_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
 | |
|    77 | 407 | 00077_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
 | |
|    87 | 407 | 00087_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
 | |
|    97 | 407 | 00097_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   107 | 407 | 00107_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   117 | 407 | 00117_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
 | |
|   127 | 407 | 00127_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
 | |
|   137 | 407 | 00137_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
 | |
|   147 | 407 | 00147_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
 | |
|   157 | 407 | 00157_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
 | |
|   167 | 407 | 00167_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
 | |
|   177 | 407 | 00177_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
 | |
|   187 | 407 | 00187_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
 | |
|   197 | 407 | 00197_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   207 | 407 | 00207_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   217 | 407 | 00217_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
 | |
|   227 | 407 | 00227_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
 | |
|   237 | 407 | 00237_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
 | |
|   247 | 407 | 00247_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
 | |
|   257 | 407 | 00257_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
 | |
|   267 | 407 | 00267_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
 | |
|   277 | 407 | 00277_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
 | |
|   287 | 407 | 00287_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
 | |
|   297 | 407 | 00297_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   307 | 407 | 00307_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   317 | 407 | 00317_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
 | |
|   327 | 407 | 00327_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
 | |
|   337 | 407 | 00337_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
 | |
|   347 | 407 | 00347_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
 | |
|   357 | 407 | 00357_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
 | |
|   367 | 407 | 00367_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
 | |
|   377 | 407 | 00377_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
 | |
|   387 | 407 | 00387_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
 | |
|   397 | 407 | 00397_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   407 | 407 | 00407_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   417 | 407 | 00417_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
 | |
|   427 | 407 | 00427_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
 | |
|   437 | 407 | 00437_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
 | |
|   447 | 407 | 00447_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
 | |
|   457 | 407 | 00457_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
 | |
|   467 | 407 | 00467_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
 | |
|   477 | 407 | 00477_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
 | |
|   487 | 407 | 00487_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
 | |
|   497 | 407 | 00497_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   507 | 407 | 00507_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   517 | 407 | 00517_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
 | |
|   527 | 407 | 00527_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
 | |
|   537 | 407 | 00537_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
 | |
|   547 | 407 | 00547_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
 | |
|   557 | 407 | 00557_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
 | |
|   567 | 407 | 00567_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
 | |
|   577 | 407 | 00577_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
 | |
|   587 | 407 | 00587_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
 | |
|   597 | 407 | 00597_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   607 | 407 | 00607_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   617 | 407 | 00617_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
 | |
|   627 | 407 | 00627_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
 | |
|   637 | 407 | 00637_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
 | |
|   647 | 407 | 00647_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
 | |
|   657 | 407 | 00657_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
 | |
|   667 | 407 | 00667_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
 | |
|   677 | 407 | 00677_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
 | |
|   687 | 407 | 00687_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
 | |
|   697 | 407 | 00697_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   707 | 407 | 00707_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   717 | 407 | 00717_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
 | |
|   727 | 407 | 00727_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
 | |
|   737 | 407 | 00737_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
 | |
|   747 | 407 | 00747_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
 | |
|   757 | 407 | 00757_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
 | |
|   767 | 407 | 00767_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
 | |
|   777 | 407 | 00777_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
 | |
|   787 | 407 | 00787_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
 | |
|   797 | 407 | 00797_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   807 | 407 | 00807_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   817 | 407 | 00817_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
 | |
|   827 | 407 | 00827_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
 | |
|   837 | 407 | 00837_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
 | |
|   847 | 407 | 00847_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
 | |
|   857 | 407 | 00857_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
 | |
|   867 | 407 | 00867_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
 | |
|   877 | 407 | 00877_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
 | |
|   887 | 407 | 00887_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
 | |
|   897 | 407 | 00897_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   907 | 407 | 00907_update7      | Thu Jan 08 00:00:00 1970 PST | Thu Jan 08 00:00:00 1970 | 7  | 7          | foo
 | |
|   917 | 407 | 00917_update7      | Sun Jan 18 00:00:00 1970 PST | Sun Jan 18 00:00:00 1970 | 7  | 7          | foo
 | |
|   927 | 407 | 00927_update7      | Wed Jan 28 00:00:00 1970 PST | Wed Jan 28 00:00:00 1970 | 7  | 7          | foo
 | |
|   937 | 407 | 00937_update7      | Sat Feb 07 00:00:00 1970 PST | Sat Feb 07 00:00:00 1970 | 7  | 7          | foo
 | |
|   947 | 407 | 00947_update7      | Tue Feb 17 00:00:00 1970 PST | Tue Feb 17 00:00:00 1970 | 7  | 7          | foo
 | |
|   957 | 407 | 00957_update7      | Fri Feb 27 00:00:00 1970 PST | Fri Feb 27 00:00:00 1970 | 7  | 7          | foo
 | |
|   967 | 407 | 00967_update7      | Mon Mar 09 00:00:00 1970 PST | Mon Mar 09 00:00:00 1970 | 7  | 7          | foo
 | |
|   977 | 407 | 00977_update7      | Thu Mar 19 00:00:00 1970 PST | Thu Mar 19 00:00:00 1970 | 7  | 7          | foo
 | |
|   987 | 407 | 00987_update7      | Sun Mar 29 00:00:00 1970 PST | Sun Mar 29 00:00:00 1970 | 7  | 7          | foo
 | |
|   997 | 407 | 00997_update7      | Wed Apr 08 00:00:00 1970 PST | Wed Apr 08 00:00:00 1970 | 7  | 7          | foo
 | |
|  1007 | 507 | 0000700007_update7 |                              |                          |    | ft2        | 
 | |
|  1017 | 507 | 0001700017_update7 |                              |                          |    | ft2        | 
 | |
| (102 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
 | |
|   FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9;                               -- can't be pushed down
 | |
|                                                                                                                                                         QUERY PLAN                                                                                                                                                         
 | |
| ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Update on public.ft2
 | |
|    Remote SQL: UPDATE "S 1"."T 1" SET c2 = $2, c3 = $3, c7 = $4 WHERE ctid = $1
 | |
|    ->  Foreign Scan
 | |
|          Output: ft2.c1, (ft2.c2 + 500), NULL::integer, (ft2.c3 || '_update9'::text), ft2.c4, ft2.c5, ft2.c6, 'ft2       '::character(10), ft2.c8, ft2.ctid, ft1.*
 | |
|          Relations: (public.ft2) INNER JOIN (public.ft1)
 | |
|          Remote SQL: SELECT r1."C 1", r1.c2, r1.c3, r1.c4, r1.c5, r1.c6, r1.c8, r1.ctid, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 9)))) FOR UPDATE OF r1
 | |
|          ->  Hash Join
 | |
|                Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c8, ft2.ctid, ft1.*
 | |
|                Hash Cond: (ft2.c2 = ft1.c1)
 | |
|                ->  Foreign Scan on public.ft2
 | |
|                      Output: ft2.c1, ft2.c2, ft2.c3, ft2.c4, ft2.c5, ft2.c6, ft2.c8, ft2.ctid
 | |
|                      Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c8, ctid FROM "S 1"."T 1" FOR UPDATE
 | |
|                ->  Hash
 | |
|                      Output: ft1.*, ft1.c1
 | |
|                      ->  Foreign Scan on public.ft1
 | |
|                            Output: ft1.*, ft1.c1
 | |
|                            Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 9))
 | |
| (17 rows)
 | |
| 
 | |
| UPDATE ft2 SET c2 = ft2.c2 + 500, c3 = ft2.c3 || '_update9', c7 = DEFAULT
 | |
|   FROM ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 9;
 | |
| EXPLAIN (verbose, costs off)
 | |
|   DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4;                               -- can be pushed down
 | |
|                                          QUERY PLAN                                         
 | |
| --------------------------------------------------------------------------------------------
 | |
|  Delete on public.ft2
 | |
|    Output: c1, c4
 | |
|    ->  Foreign Delete on public.ft2
 | |
|          Remote SQL: DELETE FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 5)) RETURNING "C 1", c4
 | |
| (4 rows)
 | |
| 
 | |
| DELETE FROM ft2 WHERE c1 % 10 = 5 RETURNING c1, c4;
 | |
|   c1  |              c4              
 | |
| ------+------------------------------
 | |
|     5 | Tue Jan 06 00:00:00 1970 PST
 | |
|    15 | Fri Jan 16 00:00:00 1970 PST
 | |
|    25 | Mon Jan 26 00:00:00 1970 PST
 | |
|    35 | Thu Feb 05 00:00:00 1970 PST
 | |
|    45 | Sun Feb 15 00:00:00 1970 PST
 | |
|    55 | Wed Feb 25 00:00:00 1970 PST
 | |
|    65 | Sat Mar 07 00:00:00 1970 PST
 | |
|    75 | Tue Mar 17 00:00:00 1970 PST
 | |
|    85 | Fri Mar 27 00:00:00 1970 PST
 | |
|    95 | Mon Apr 06 00:00:00 1970 PST
 | |
|   105 | Tue Jan 06 00:00:00 1970 PST
 | |
|   115 | Fri Jan 16 00:00:00 1970 PST
 | |
|   125 | Mon Jan 26 00:00:00 1970 PST
 | |
|   135 | Thu Feb 05 00:00:00 1970 PST
 | |
|   145 | Sun Feb 15 00:00:00 1970 PST
 | |
|   155 | Wed Feb 25 00:00:00 1970 PST
 | |
|   165 | Sat Mar 07 00:00:00 1970 PST
 | |
|   175 | Tue Mar 17 00:00:00 1970 PST
 | |
|   185 | Fri Mar 27 00:00:00 1970 PST
 | |
|   195 | Mon Apr 06 00:00:00 1970 PST
 | |
|   205 | Tue Jan 06 00:00:00 1970 PST
 | |
|   215 | Fri Jan 16 00:00:00 1970 PST
 | |
|   225 | Mon Jan 26 00:00:00 1970 PST
 | |
|   235 | Thu Feb 05 00:00:00 1970 PST
 | |
|   245 | Sun Feb 15 00:00:00 1970 PST
 | |
|   255 | Wed Feb 25 00:00:00 1970 PST
 | |
|   265 | Sat Mar 07 00:00:00 1970 PST
 | |
|   275 | Tue Mar 17 00:00:00 1970 PST
 | |
|   285 | Fri Mar 27 00:00:00 1970 PST
 | |
|   295 | Mon Apr 06 00:00:00 1970 PST
 | |
|   305 | Tue Jan 06 00:00:00 1970 PST
 | |
|   315 | Fri Jan 16 00:00:00 1970 PST
 | |
|   325 | Mon Jan 26 00:00:00 1970 PST
 | |
|   335 | Thu Feb 05 00:00:00 1970 PST
 | |
|   345 | Sun Feb 15 00:00:00 1970 PST
 | |
|   355 | Wed Feb 25 00:00:00 1970 PST
 | |
|   365 | Sat Mar 07 00:00:00 1970 PST
 | |
|   375 | Tue Mar 17 00:00:00 1970 PST
 | |
|   385 | Fri Mar 27 00:00:00 1970 PST
 | |
|   395 | Mon Apr 06 00:00:00 1970 PST
 | |
|   405 | Tue Jan 06 00:00:00 1970 PST
 | |
|   415 | Fri Jan 16 00:00:00 1970 PST
 | |
|   425 | Mon Jan 26 00:00:00 1970 PST
 | |
|   435 | Thu Feb 05 00:00:00 1970 PST
 | |
|   445 | Sun Feb 15 00:00:00 1970 PST
 | |
|   455 | Wed Feb 25 00:00:00 1970 PST
 | |
|   465 | Sat Mar 07 00:00:00 1970 PST
 | |
|   475 | Tue Mar 17 00:00:00 1970 PST
 | |
|   485 | Fri Mar 27 00:00:00 1970 PST
 | |
|   495 | Mon Apr 06 00:00:00 1970 PST
 | |
|   505 | Tue Jan 06 00:00:00 1970 PST
 | |
|   515 | Fri Jan 16 00:00:00 1970 PST
 | |
|   525 | Mon Jan 26 00:00:00 1970 PST
 | |
|   535 | Thu Feb 05 00:00:00 1970 PST
 | |
|   545 | Sun Feb 15 00:00:00 1970 PST
 | |
|   555 | Wed Feb 25 00:00:00 1970 PST
 | |
|   565 | Sat Mar 07 00:00:00 1970 PST
 | |
|   575 | Tue Mar 17 00:00:00 1970 PST
 | |
|   585 | Fri Mar 27 00:00:00 1970 PST
 | |
|   595 | Mon Apr 06 00:00:00 1970 PST
 | |
|   605 | Tue Jan 06 00:00:00 1970 PST
 | |
|   615 | Fri Jan 16 00:00:00 1970 PST
 | |
|   625 | Mon Jan 26 00:00:00 1970 PST
 | |
|   635 | Thu Feb 05 00:00:00 1970 PST
 | |
|   645 | Sun Feb 15 00:00:00 1970 PST
 | |
|   655 | Wed Feb 25 00:00:00 1970 PST
 | |
|   665 | Sat Mar 07 00:00:00 1970 PST
 | |
|   675 | Tue Mar 17 00:00:00 1970 PST
 | |
|   685 | Fri Mar 27 00:00:00 1970 PST
 | |
|   695 | Mon Apr 06 00:00:00 1970 PST
 | |
|   705 | Tue Jan 06 00:00:00 1970 PST
 | |
|   715 | Fri Jan 16 00:00:00 1970 PST
 | |
|   725 | Mon Jan 26 00:00:00 1970 PST
 | |
|   735 | Thu Feb 05 00:00:00 1970 PST
 | |
|   745 | Sun Feb 15 00:00:00 1970 PST
 | |
|   755 | Wed Feb 25 00:00:00 1970 PST
 | |
|   765 | Sat Mar 07 00:00:00 1970 PST
 | |
|   775 | Tue Mar 17 00:00:00 1970 PST
 | |
|   785 | Fri Mar 27 00:00:00 1970 PST
 | |
|   795 | Mon Apr 06 00:00:00 1970 PST
 | |
|   805 | Tue Jan 06 00:00:00 1970 PST
 | |
|   815 | Fri Jan 16 00:00:00 1970 PST
 | |
|   825 | Mon Jan 26 00:00:00 1970 PST
 | |
|   835 | Thu Feb 05 00:00:00 1970 PST
 | |
|   845 | Sun Feb 15 00:00:00 1970 PST
 | |
|   855 | Wed Feb 25 00:00:00 1970 PST
 | |
|   865 | Sat Mar 07 00:00:00 1970 PST
 | |
|   875 | Tue Mar 17 00:00:00 1970 PST
 | |
|   885 | Fri Mar 27 00:00:00 1970 PST
 | |
|   895 | Mon Apr 06 00:00:00 1970 PST
 | |
|   905 | Tue Jan 06 00:00:00 1970 PST
 | |
|   915 | Fri Jan 16 00:00:00 1970 PST
 | |
|   925 | Mon Jan 26 00:00:00 1970 PST
 | |
|   935 | Thu Feb 05 00:00:00 1970 PST
 | |
|   945 | Sun Feb 15 00:00:00 1970 PST
 | |
|   955 | Wed Feb 25 00:00:00 1970 PST
 | |
|   965 | Sat Mar 07 00:00:00 1970 PST
 | |
|   975 | Tue Mar 17 00:00:00 1970 PST
 | |
|   985 | Fri Mar 27 00:00:00 1970 PST
 | |
|   995 | Mon Apr 06 00:00:00 1970 PST
 | |
|  1005 | 
 | |
|  1015 | 
 | |
|  1105 | 
 | |
| (103 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;                -- can't be pushed down
 | |
|                                                                                                                               QUERY PLAN                                                                                                                               
 | |
| -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Delete on public.ft2
 | |
|    Remote SQL: DELETE FROM "S 1"."T 1" WHERE ctid = $1
 | |
|    ->  Foreign Scan
 | |
|          Output: ft2.ctid, ft1.*
 | |
|          Relations: (public.ft2) INNER JOIN (public.ft1)
 | |
|          Remote SQL: SELECT r1.ctid, CASE WHEN (r2.*)::text IS NOT NULL THEN ROW(r2."C 1", r2.c2, r2.c3, r2.c4, r2.c5, r2.c6, r2.c7, r2.c8) END FROM ("S 1"."T 1" r1 INNER JOIN "S 1"."T 1" r2 ON (((r1.c2 = r2."C 1")) AND (((r2."C 1" % 10) = 2)))) FOR UPDATE OF r1
 | |
|          ->  Hash Join
 | |
|                Output: ft2.ctid, ft1.*
 | |
|                Hash Cond: (ft2.c2 = ft1.c1)
 | |
|                ->  Foreign Scan on public.ft2
 | |
|                      Output: ft2.ctid, ft2.c2
 | |
|                      Remote SQL: SELECT c2, ctid FROM "S 1"."T 1" FOR UPDATE
 | |
|                ->  Hash
 | |
|                      Output: ft1.*, ft1.c1
 | |
|                      ->  Foreign Scan on public.ft1
 | |
|                            Output: ft1.*, ft1.c1
 | |
|                            Remote SQL: SELECT "C 1", c2, c3, c4, c5, c6, c7, c8 FROM "S 1"."T 1" WHERE ((("C 1" % 10) = 2))
 | |
| (17 rows)
 | |
| 
 | |
| DELETE FROM ft2 USING ft1 WHERE ft1.c1 = ft2.c2 AND ft1.c1 % 10 = 2;
 | |
| SELECT c1,c2,c3,c4 FROM ft2 ORDER BY c1;
 | |
|   c1  | c2  |         c3         |              c4              
 | |
| ------+-----+--------------------+------------------------------
 | |
|     1 |   1 | 00001              | Fri Jan 02 00:00:00 1970 PST
 | |
|     3 | 303 | 00003_update3      | Sun Jan 04 00:00:00 1970 PST
 | |
|     4 |   4 | 00004              | Mon Jan 05 00:00:00 1970 PST
 | |
|     6 |   6 | 00006              | Wed Jan 07 00:00:00 1970 PST
 | |
|     7 | 407 | 00007_update7      | Thu Jan 08 00:00:00 1970 PST
 | |
|     8 |   8 | 00008              | Fri Jan 09 00:00:00 1970 PST
 | |
|     9 | 509 | 00009_update9      | Sat Jan 10 00:00:00 1970 PST
 | |
|    10 |   0 | 00010              | Sun Jan 11 00:00:00 1970 PST
 | |
|    11 |   1 | 00011              | Mon Jan 12 00:00:00 1970 PST
 | |
|    13 | 303 | 00013_update3      | Wed Jan 14 00:00:00 1970 PST
 | |
|    14 |   4 | 00014              | Thu Jan 15 00:00:00 1970 PST
 | |
|    16 |   6 | 00016              | Sat Jan 17 00:00:00 1970 PST
 | |
|    17 | 407 | 00017_update7      | Sun Jan 18 00:00:00 1970 PST
 | |
|    18 |   8 | 00018              | Mon Jan 19 00:00:00 1970 PST
 | |
|    19 | 509 | 00019_update9      | Tue Jan 20 00:00:00 1970 PST
 | |
|    20 |   0 | 00020              | Wed Jan 21 00:00:00 1970 PST
 | |
|    21 |   1 | 00021              | Thu Jan 22 00:00:00 1970 PST
 | |
|    23 | 303 | 00023_update3      | Sat Jan 24 00:00:00 1970 PST
 | |
|    24 |   4 | 00024              | Sun Jan 25 00:00:00 1970 PST
 | |
|    26 |   6 | 00026              | Tue Jan 27 00:00:00 1970 PST
 | |
|    27 | 407 | 00027_update7      | Wed Jan 28 00:00:00 1970 PST
 | |
|    28 |   8 | 00028              | Thu Jan 29 00:00:00 1970 PST
 | |
|    29 | 509 | 00029_update9      | Fri Jan 30 00:00:00 1970 PST
 | |
|    30 |   0 | 00030              | Sat Jan 31 00:00:00 1970 PST
 | |
|    31 |   1 | 00031              | Sun Feb 01 00:00:00 1970 PST
 | |
|    33 | 303 | 00033_update3      | Tue Feb 03 00:00:00 1970 PST
 | |
|    34 |   4 | 00034              | Wed Feb 04 00:00:00 1970 PST
 | |
|    36 |   6 | 00036              | Fri Feb 06 00:00:00 1970 PST
 | |
|    37 | 407 | 00037_update7      | Sat Feb 07 00:00:00 1970 PST
 | |
|    38 |   8 | 00038              | Sun Feb 08 00:00:00 1970 PST
 | |
|    39 | 509 | 00039_update9      | Mon Feb 09 00:00:00 1970 PST
 | |
|    40 |   0 | 00040              | Tue Feb 10 00:00:00 1970 PST
 | |
|    41 |   1 | 00041              | Wed Feb 11 00:00:00 1970 PST
 | |
|    43 | 303 | 00043_update3      | Fri Feb 13 00:00:00 1970 PST
 | |
|    44 |   4 | 00044              | Sat Feb 14 00:00:00 1970 PST
 | |
|    46 |   6 | 00046              | Mon Feb 16 00:00:00 1970 PST
 | |
|    47 | 407 | 00047_update7      | Tue Feb 17 00:00:00 1970 PST
 | |
|    48 |   8 | 00048              | Wed Feb 18 00:00:00 1970 PST
 | |
|    49 | 509 | 00049_update9      | Thu Feb 19 00:00:00 1970 PST
 | |
|    50 |   0 | 00050              | Fri Feb 20 00:00:00 1970 PST
 | |
|    51 |   1 | 00051              | Sat Feb 21 00:00:00 1970 PST
 | |
|    53 | 303 | 00053_update3      | Mon Feb 23 00:00:00 1970 PST
 | |
|    54 |   4 | 00054              | Tue Feb 24 00:00:00 1970 PST
 | |
|    56 |   6 | 00056              | Thu Feb 26 00:00:00 1970 PST
 | |
|    57 | 407 | 00057_update7      | Fri Feb 27 00:00:00 1970 PST
 | |
|    58 |   8 | 00058              | Sat Feb 28 00:00:00 1970 PST
 | |
|    59 | 509 | 00059_update9      | Sun Mar 01 00:00:00 1970 PST
 | |
|    60 |   0 | 00060              | Mon Mar 02 00:00:00 1970 PST
 | |
|    61 |   1 | 00061              | Tue Mar 03 00:00:00 1970 PST
 | |
|    63 | 303 | 00063_update3      | Thu Mar 05 00:00:00 1970 PST
 | |
|    64 |   4 | 00064              | Fri Mar 06 00:00:00 1970 PST
 | |
|    66 |   6 | 00066              | Sun Mar 08 00:00:00 1970 PST
 | |
|    67 | 407 | 00067_update7      | Mon Mar 09 00:00:00 1970 PST
 | |
|    68 |   8 | 00068              | Tue Mar 10 00:00:00 1970 PST
 | |
|    69 | 509 | 00069_update9      | Wed Mar 11 00:00:00 1970 PST
 | |
|    70 |   0 | 00070              | Thu Mar 12 00:00:00 1970 PST
 | |
|    71 |   1 | 00071              | Fri Mar 13 00:00:00 1970 PST
 | |
|    73 | 303 | 00073_update3      | Sun Mar 15 00:00:00 1970 PST
 | |
|    74 |   4 | 00074              | Mon Mar 16 00:00:00 1970 PST
 | |
|    76 |   6 | 00076              | Wed Mar 18 00:00:00 1970 PST
 | |
|    77 | 407 | 00077_update7      | Thu Mar 19 00:00:00 1970 PST
 | |
|    78 |   8 | 00078              | Fri Mar 20 00:00:00 1970 PST
 | |
|    79 | 509 | 00079_update9      | Sat Mar 21 00:00:00 1970 PST
 | |
|    80 |   0 | 00080              | Sun Mar 22 00:00:00 1970 PST
 | |
|    81 |   1 | 00081              | Mon Mar 23 00:00:00 1970 PST
 | |
|    83 | 303 | 00083_update3      | Wed Mar 25 00:00:00 1970 PST
 | |
|    84 |   4 | 00084              | Thu Mar 26 00:00:00 1970 PST
 | |
|    86 |   6 | 00086              | Sat Mar 28 00:00:00 1970 PST
 | |
|    87 | 407 | 00087_update7      | Sun Mar 29 00:00:00 1970 PST
 | |
|    88 |   8 | 00088              | Mon Mar 30 00:00:00 1970 PST
 | |
|    89 | 509 | 00089_update9      | Tue Mar 31 00:00:00 1970 PST
 | |
|    90 |   0 | 00090              | Wed Apr 01 00:00:00 1970 PST
 | |
|    91 |   1 | 00091              | Thu Apr 02 00:00:00 1970 PST
 | |
|    93 | 303 | 00093_update3      | Sat Apr 04 00:00:00 1970 PST
 | |
|    94 |   4 | 00094              | Sun Apr 05 00:00:00 1970 PST
 | |
|    96 |   6 | 00096              | Tue Apr 07 00:00:00 1970 PST
 | |
|    97 | 407 | 00097_update7      | Wed Apr 08 00:00:00 1970 PST
 | |
|    98 |   8 | 00098              | Thu Apr 09 00:00:00 1970 PST
 | |
|    99 | 509 | 00099_update9      | Fri Apr 10 00:00:00 1970 PST
 | |
|   100 |   0 | 00100              | Thu Jan 01 00:00:00 1970 PST
 | |
|   101 |   1 | 00101              | Fri Jan 02 00:00:00 1970 PST
 | |
|   103 | 303 | 00103_update3      | Sun Jan 04 00:00:00 1970 PST
 | |
|   104 |   4 | 00104              | Mon Jan 05 00:00:00 1970 PST
 | |
|   106 |   6 | 00106              | Wed Jan 07 00:00:00 1970 PST
 | |
|   107 | 407 | 00107_update7      | Thu Jan 08 00:00:00 1970 PST
 | |
|   108 |   8 | 00108              | Fri Jan 09 00:00:00 1970 PST
 | |
|   109 | 509 | 00109_update9      | Sat Jan 10 00:00:00 1970 PST
 | |
|   110 |   0 | 00110              | Sun Jan 11 00:00:00 1970 PST
 | |
|   111 |   1 | 00111              | Mon Jan 12 00:00:00 1970 PST
 | |
|   113 | 303 | 00113_update3      | Wed Jan 14 00:00:00 1970 PST
 | |
|   114 |   4 | 00114              | Thu Jan 15 00:00:00 1970 PST
 | |
|   116 |   6 | 00116              | Sat Jan 17 00:00:00 1970 PST
 | |
|   117 | 407 | 00117_update7      | Sun Jan 18 00:00:00 1970 PST
 | |
|   118 |   8 | 00118              | Mon Jan 19 00:00:00 1970 PST
 | |
|   119 | 509 | 00119_update9      | Tue Jan 20 00:00:00 1970 PST
 | |
|   120 |   0 | 00120              | Wed Jan 21 00:00:00 1970 PST
 | |
|   121 |   1 | 00121              | Thu Jan 22 00:00:00 1970 PST
 | |
|   123 | 303 | 00123_update3      | Sat Jan 24 00:00:00 1970 PST
 | |
|   124 |   4 | 00124              | Sun Jan 25 00:00:00 1970 PST
 | |
|   126 |   6 | 00126              | Tue Jan 27 00:00:00 1970 PST
 | |
|   127 | 407 | 00127_update7      | Wed Jan 28 00:00:00 1970 PST
 | |
|   128 |   8 | 00128              | Thu Jan 29 00:00:00 1970 PST
 | |
|   129 | 509 | 00129_update9      | Fri Jan 30 00:00:00 1970 PST
 | |
|   130 |   0 | 00130              | Sat Jan 31 00:00:00 1970 PST
 | |
|   131 |   1 | 00131              | Sun Feb 01 00:00:00 1970 PST
 | |
|   133 | 303 | 00133_update3      | Tue Feb 03 00:00:00 1970 PST
 | |
|   134 |   4 | 00134              | Wed Feb 04 00:00:00 1970 PST
 | |
|   136 |   6 | 00136              | Fri Feb 06 00:00:00 1970 PST
 | |
|   137 | 407 | 00137_update7      | Sat Feb 07 00:00:00 1970 PST
 | |
|   138 |   8 | 00138              | Sun Feb 08 00:00:00 1970 PST
 | |
|   139 | 509 | 00139_update9      | Mon Feb 09 00:00:00 1970 PST
 | |
|   140 |   0 | 00140              | Tue Feb 10 00:00:00 1970 PST
 | |
|   141 |   1 | 00141              | Wed Feb 11 00:00:00 1970 PST
 | |
|   143 | 303 | 00143_update3      | Fri Feb 13 00:00:00 1970 PST
 | |
|   144 |   4 | 00144              | Sat Feb 14 00:00:00 1970 PST
 | |
|   146 |   6 | 00146              | Mon Feb 16 00:00:00 1970 PST
 | |
|   147 | 407 | 00147_update7      | Tue Feb 17 00:00:00 1970 PST
 | |
|   148 |   8 | 00148              | Wed Feb 18 00:00:00 1970 PST
 | |
|   149 | 509 | 00149_update9      | Thu Feb 19 00:00:00 1970 PST
 | |
|   150 |   0 | 00150              | Fri Feb 20 00:00:00 1970 PST
 | |
|   151 |   1 | 00151              | Sat Feb 21 00:00:00 1970 PST
 | |
|   153 | 303 | 00153_update3      | Mon Feb 23 00:00:00 1970 PST
 | |
|   154 |   4 | 00154              | Tue Feb 24 00:00:00 1970 PST
 | |
|   156 |   6 | 00156              | Thu Feb 26 00:00:00 1970 PST
 | |
|   157 | 407 | 00157_update7      | Fri Feb 27 00:00:00 1970 PST
 | |
|   158 |   8 | 00158              | Sat Feb 28 00:00:00 1970 PST
 | |
|   159 | 509 | 00159_update9      | Sun Mar 01 00:00:00 1970 PST
 | |
|   160 |   0 | 00160              | Mon Mar 02 00:00:00 1970 PST
 | |
|   161 |   1 | 00161              | Tue Mar 03 00:00:00 1970 PST
 | |
|   163 | 303 | 00163_update3      | Thu Mar 05 00:00:00 1970 PST
 | |
|   164 |   4 | 00164              | Fri Mar 06 00:00:00 1970 PST
 | |
|   166 |   6 | 00166              | Sun Mar 08 00:00:00 1970 PST
 | |
|   167 | 407 | 00167_update7      | Mon Mar 09 00:00:00 1970 PST
 | |
|   168 |   8 | 00168              | Tue Mar 10 00:00:00 1970 PST
 | |
|   169 | 509 | 00169_update9      | Wed Mar 11 00:00:00 1970 PST
 | |
|   170 |   0 | 00170              | Thu Mar 12 00:00:00 1970 PST
 | |
|   171 |   1 | 00171              | Fri Mar 13 00:00:00 1970 PST
 | |
|   173 | 303 | 00173_update3      | Sun Mar 15 00:00:00 1970 PST
 | |
|   174 |   4 | 00174              | Mon Mar 16 00:00:00 1970 PST
 | |
|   176 |   6 | 00176              | Wed Mar 18 00:00:00 1970 PST
 | |
|   177 | 407 | 00177_update7      | Thu Mar 19 00:00:00 1970 PST
 | |
|   178 |   8 | 00178              | Fri Mar 20 00:00:00 1970 PST
 | |
|   179 | 509 | 00179_update9      | Sat Mar 21 00:00:00 1970 PST
 | |
|   180 |   0 | 00180              | Sun Mar 22 00:00:00 1970 PST
 | |
|   181 |   1 | 00181              | Mon Mar 23 00:00:00 1970 PST
 | |
|   183 | 303 | 00183_update3      | Wed Mar 25 00:00:00 1970 PST
 | |
|   184 |   4 | 00184              | Thu Mar 26 00:00:00 1970 PST
 | |
|   186 |   6 | 00186              | Sat Mar 28 00:00:00 1970 PST
 | |
|   187 | 407 | 00187_update7      | Sun Mar 29 00:00:00 1970 PST
 | |
|   188 |   8 | 00188              | Mon Mar 30 00:00:00 1970 PST
 | |
|   189 | 509 | 00189_update9      | Tue Mar 31 00:00:00 1970 PST
 | |
|   190 |   0 | 00190              | Wed Apr 01 00:00:00 1970 PST
 | |
|   191 |   1 | 00191              | Thu Apr 02 00:00:00 1970 PST
 | |
|   193 | 303 | 00193_update3      | Sat Apr 04 00:00:00 1970 PST
 | |
|   194 |   4 | 00194              | Sun Apr 05 00:00:00 1970 PST
 | |
|   196 |   6 | 00196              | Tue Apr 07 00:00:00 1970 PST
 | |
|   197 | 407 | 00197_update7      | Wed Apr 08 00:00:00 1970 PST
 | |
|   198 |   8 | 00198              | Thu Apr 09 00:00:00 1970 PST
 | |
|   199 | 509 | 00199_update9      | Fri Apr 10 00:00:00 1970 PST
 | |
|   200 |   0 | 00200              | Thu Jan 01 00:00:00 1970 PST
 | |
|   201 |   1 | 00201              | Fri Jan 02 00:00:00 1970 PST
 | |
|   203 | 303 | 00203_update3      | Sun Jan 04 00:00:00 1970 PST
 | |
|   204 |   4 | 00204              | Mon Jan 05 00:00:00 1970 PST
 | |
|   206 |   6 | 00206              | Wed Jan 07 00:00:00 1970 PST
 | |
|   207 | 407 | 00207_update7      | Thu Jan 08 00:00:00 1970 PST
 | |
|   208 |   8 | 00208              | Fri Jan 09 00:00:00 1970 PST
 | |
|   209 | 509 | 00209_update9      | Sat Jan 10 00:00:00 1970 PST
 | |
|   210 |   0 | 00210              | Sun Jan 11 00:00:00 1970 PST
 | |
|   211 |   1 | 00211              | Mon Jan 12 00:00:00 1970 PST
 | |
|   213 | 303 | 00213_update3      | Wed Jan 14 00:00:00 1970 PST
 | |
|   214 |   4 | 00214              | Thu Jan 15 00:00:00 1970 PST
 | |
|   216 |   6 | 00216              | Sat Jan 17 00:00:00 1970 PST
 | |
|   217 | 407 | 00217_update7      | Sun Jan 18 00:00:00 1970 PST
 | |
|   218 |   8 | 00218              | Mon Jan 19 00:00:00 1970 PST
 | |
|   219 | 509 | 00219_update9      | Tue Jan 20 00:00:00 1970 PST
 | |
|   220 |   0 | 00220              | Wed Jan 21 00:00:00 1970 PST
 | |
|   221 |   1 | 00221              | Thu Jan 22 00:00:00 1970 PST
 | |
|   223 | 303 | 00223_update3      | Sat Jan 24 00:00:00 1970 PST
 | |
|   224 |   4 | 00224              | Sun Jan 25 00:00:00 1970 PST
 | |
|   226 |   6 | 00226              | Tue Jan 27 00:00:00 1970 PST
 | |
|   227 | 407 | 00227_update7      | Wed Jan 28 00:00:00 1970 PST
 | |
|   228 |   8 | 00228              | Thu Jan 29 00:00:00 1970 PST
 | |
|   229 | 509 | 00229_update9      | Fri Jan 30 00:00:00 1970 PST
 | |
|   230 |   0 | 00230              | Sat Jan 31 00:00:00 1970 PST
 | |
|   231 |   1 | 00231              | Sun Feb 01 00:00:00 1970 PST
 | |
|   233 | 303 | 00233_update3      | Tue Feb 03 00:00:00 1970 PST
 | |
|   234 |   4 | 00234              | Wed Feb 04 00:00:00 1970 PST
 | |
|   236 |   6 | 00236              | Fri Feb 06 00:00:00 1970 PST
 | |
|   237 | 407 | 00237_update7      | Sat Feb 07 00:00:00 1970 PST
 | |
|   238 |   8 | 00238              | Sun Feb 08 00:00:00 1970 PST
 | |
|   239 | 509 | 00239_update9      | Mon Feb 09 00:00:00 1970 PST
 | |
|   240 |   0 | 00240              | Tue Feb 10 00:00:00 1970 PST
 | |
|   241 |   1 | 00241              | Wed Feb 11 00:00:00 1970 PST
 | |
|   243 | 303 | 00243_update3      | Fri Feb 13 00:00:00 1970 PST
 | |
|   244 |   4 | 00244              | Sat Feb 14 00:00:00 1970 PST
 | |
|   246 |   6 | 00246              | Mon Feb 16 00:00:00 1970 PST
 | |
|   247 | 407 | 00247_update7      | Tue Feb 17 00:00:00 1970 PST
 | |
|   248 |   8 | 00248              | Wed Feb 18 00:00:00 1970 PST
 | |
|   249 | 509 | 00249_update9      | Thu Feb 19 00:00:00 1970 PST
 | |
|   250 |   0 | 00250              | Fri Feb 20 00:00:00 1970 PST
 | |
|   251 |   1 | 00251              | Sat Feb 21 00:00:00 1970 PST
 | |
|   253 | 303 | 00253_update3      | Mon Feb 23 00:00:00 1970 PST
 | |
|   254 |   4 | 00254              | Tue Feb 24 00:00:00 1970 PST
 | |
|   256 |   6 | 00256              | Thu Feb 26 00:00:00 1970 PST
 | |
|   257 | 407 | 00257_update7      | Fri Feb 27 00:00:00 1970 PST
 | |
|   258 |   8 | 00258              | Sat Feb 28 00:00:00 1970 PST
 | |
|   259 | 509 | 00259_update9      | Sun Mar 01 00:00:00 1970 PST
 | |
|   260 |   0 | 00260              | Mon Mar 02 00:00:00 1970 PST
 | |
|   261 |   1 | 00261              | Tue Mar 03 00:00:00 1970 PST
 | |
|   263 | 303 | 00263_update3      | Thu Mar 05 00:00:00 1970 PST
 | |
|   264 |   4 | 00264              | Fri Mar 06 00:00:00 1970 PST
 | |
|   266 |   6 | 00266              | Sun Mar 08 00:00:00 1970 PST
 | |
|   267 | 407 | 00267_update7      | Mon Mar 09 00:00:00 1970 PST
 | |
|   268 |   8 | 00268              | Tue Mar 10 00:00:00 1970 PST
 | |
|   269 | 509 | 00269_update9      | Wed Mar 11 00:00:00 1970 PST
 | |
|   270 |   0 | 00270              | Thu Mar 12 00:00:00 1970 PST
 | |
|   271 |   1 | 00271              | Fri Mar 13 00:00:00 1970 PST
 | |
|   273 | 303 | 00273_update3      | Sun Mar 15 00:00:00 1970 PST
 | |
|   274 |   4 | 00274              | Mon Mar 16 00:00:00 1970 PST
 | |
|   276 |   6 | 00276              | Wed Mar 18 00:00:00 1970 PST
 | |
|   277 | 407 | 00277_update7      | Thu Mar 19 00:00:00 1970 PST
 | |
|   278 |   8 | 00278              | Fri Mar 20 00:00:00 1970 PST
 | |
|   279 | 509 | 00279_update9      | Sat Mar 21 00:00:00 1970 PST
 | |
|   280 |   0 | 00280              | Sun Mar 22 00:00:00 1970 PST
 | |
|   281 |   1 | 00281              | Mon Mar 23 00:00:00 1970 PST
 | |
|   283 | 303 | 00283_update3      | Wed Mar 25 00:00:00 1970 PST
 | |
|   284 |   4 | 00284              | Thu Mar 26 00:00:00 1970 PST
 | |
|   286 |   6 | 00286              | Sat Mar 28 00:00:00 1970 PST
 | |
|   287 | 407 | 00287_update7      | Sun Mar 29 00:00:00 1970 PST
 | |
|   288 |   8 | 00288              | Mon Mar 30 00:00:00 1970 PST
 | |
|   289 | 509 | 00289_update9      | Tue Mar 31 00:00:00 1970 PST
 | |
|   290 |   0 | 00290              | Wed Apr 01 00:00:00 1970 PST
 | |
|   291 |   1 | 00291              | Thu Apr 02 00:00:00 1970 PST
 | |
|   293 | 303 | 00293_update3      | Sat Apr 04 00:00:00 1970 PST
 | |
|   294 |   4 | 00294              | Sun Apr 05 00:00:00 1970 PST
 | |
|   296 |   6 | 00296              | Tue Apr 07 00:00:00 1970 PST
 | |
|   297 | 407 | 00297_update7      | Wed Apr 08 00:00:00 1970 PST
 | |
|   298 |   8 | 00298              | Thu Apr 09 00:00:00 1970 PST
 | |
|   299 | 509 | 00299_update9      | Fri Apr 10 00:00:00 1970 PST
 | |
|   300 |   0 | 00300              | Thu Jan 01 00:00:00 1970 PST
 | |
|   301 |   1 | 00301              | Fri Jan 02 00:00:00 1970 PST
 | |
|   303 | 303 | 00303_update3      | Sun Jan 04 00:00:00 1970 PST
 | |
|   304 |   4 | 00304              | Mon Jan 05 00:00:00 1970 PST
 | |
|   306 |   6 | 00306              | Wed Jan 07 00:00:00 1970 PST
 | |
|   307 | 407 | 00307_update7      | Thu Jan 08 00:00:00 1970 PST
 | |
|   308 |   8 | 00308              | Fri Jan 09 00:00:00 1970 PST
 | |
|   309 | 509 | 00309_update9      | Sat Jan 10 00:00:00 1970 PST
 | |
|   310 |   0 | 00310              | Sun Jan 11 00:00:00 1970 PST
 | |
|   311 |   1 | 00311              | Mon Jan 12 00:00:00 1970 PST
 | |
|   313 | 303 | 00313_update3      | Wed Jan 14 00:00:00 1970 PST
 | |
|   314 |   4 | 00314              | Thu Jan 15 00:00:00 1970 PST
 | |
|   316 |   6 | 00316              | Sat Jan 17 00:00:00 1970 PST
 | |
|   317 | 407 | 00317_update7      | Sun Jan 18 00:00:00 1970 PST
 | |
|   318 |   8 | 00318              | Mon Jan 19 00:00:00 1970 PST
 | |
|   319 | 509 | 00319_update9      | Tue Jan 20 00:00:00 1970 PST
 | |
|   320 |   0 | 00320              | Wed Jan 21 00:00:00 1970 PST
 | |
|   321 |   1 | 00321              | Thu Jan 22 00:00:00 1970 PST
 | |
|   323 | 303 | 00323_update3      | Sat Jan 24 00:00:00 1970 PST
 | |
|   324 |   4 | 00324              | Sun Jan 25 00:00:00 1970 PST
 | |
|   326 |   6 | 00326              | Tue Jan 27 00:00:00 1970 PST
 | |
|   327 | 407 | 00327_update7      | Wed Jan 28 00:00:00 1970 PST
 | |
|   328 |   8 | 00328              | Thu Jan 29 00:00:00 1970 PST
 | |
|   329 | 509 | 00329_update9      | Fri Jan 30 00:00:00 1970 PST
 | |
|   330 |   0 | 00330              | Sat Jan 31 00:00:00 1970 PST
 | |
|   331 |   1 | 00331              | Sun Feb 01 00:00:00 1970 PST
 | |
|   333 | 303 | 00333_update3      | Tue Feb 03 00:00:00 1970 PST
 | |
|   334 |   4 | 00334              | Wed Feb 04 00:00:00 1970 PST
 | |
|   336 |   6 | 00336              | Fri Feb 06 00:00:00 1970 PST
 | |
|   337 | 407 | 00337_update7      | Sat Feb 07 00:00:00 1970 PST
 | |
|   338 |   8 | 00338              | Sun Feb 08 00:00:00 1970 PST
 | |
|   339 | 509 | 00339_update9      | Mon Feb 09 00:00:00 1970 PST
 | |
|   340 |   0 | 00340              | Tue Feb 10 00:00:00 1970 PST
 | |
|   341 |   1 | 00341              | Wed Feb 11 00:00:00 1970 PST
 | |
|   343 | 303 | 00343_update3      | Fri Feb 13 00:00:00 1970 PST
 | |
|   344 |   4 | 00344              | Sat Feb 14 00:00:00 1970 PST
 | |
|   346 |   6 | 00346              | Mon Feb 16 00:00:00 1970 PST
 | |
|   347 | 407 | 00347_update7      | Tue Feb 17 00:00:00 1970 PST
 | |
|   348 |   8 | 00348              | Wed Feb 18 00:00:00 1970 PST
 | |
|   349 | 509 | 00349_update9      | Thu Feb 19 00:00:00 1970 PST
 | |
|   350 |   0 | 00350              | Fri Feb 20 00:00:00 1970 PST
 | |
|   351 |   1 | 00351              | Sat Feb 21 00:00:00 1970 PST
 | |
|   353 | 303 | 00353_update3      | Mon Feb 23 00:00:00 1970 PST
 | |
|   354 |   4 | 00354              | Tue Feb 24 00:00:00 1970 PST
 | |
|   356 |   6 | 00356              | Thu Feb 26 00:00:00 1970 PST
 | |
|   357 | 407 | 00357_update7      | Fri Feb 27 00:00:00 1970 PST
 | |
|   358 |   8 | 00358              | Sat Feb 28 00:00:00 1970 PST
 | |
|   359 | 509 | 00359_update9      | Sun Mar 01 00:00:00 1970 PST
 | |
|   360 |   0 | 00360              | Mon Mar 02 00:00:00 1970 PST
 | |
|   361 |   1 | 00361              | Tue Mar 03 00:00:00 1970 PST
 | |
|   363 | 303 | 00363_update3      | Thu Mar 05 00:00:00 1970 PST
 | |
|   364 |   4 | 00364              | Fri Mar 06 00:00:00 1970 PST
 | |
|   366 |   6 | 00366              | Sun Mar 08 00:00:00 1970 PST
 | |
|   367 | 407 | 00367_update7      | Mon Mar 09 00:00:00 1970 PST
 | |
|   368 |   8 | 00368              | Tue Mar 10 00:00:00 1970 PST
 | |
|   369 | 509 | 00369_update9      | Wed Mar 11 00:00:00 1970 PST
 | |
|   370 |   0 | 00370              | Thu Mar 12 00:00:00 1970 PST
 | |
|   371 |   1 | 00371              | Fri Mar 13 00:00:00 1970 PST
 | |
|   373 | 303 | 00373_update3      | Sun Mar 15 00:00:00 1970 PST
 | |
|   374 |   4 | 00374              | Mon Mar 16 00:00:00 1970 PST
 | |
|   376 |   6 | 00376              | Wed Mar 18 00:00:00 1970 PST
 | |
|   377 | 407 | 00377_update7      | Thu Mar 19 00:00:00 1970 PST
 | |
|   378 |   8 | 00378              | Fri Mar 20 00:00:00 1970 PST
 | |
|   379 | 509 | 00379_update9      | Sat Mar 21 00:00:00 1970 PST
 | |
|   380 |   0 | 00380              | Sun Mar 22 00:00:00 1970 PST
 | |
|   381 |   1 | 00381              | Mon Mar 23 00:00:00 1970 PST
 | |
|   383 | 303 | 00383_update3      | Wed Mar 25 00:00:00 1970 PST
 | |
|   384 |   4 | 00384              | Thu Mar 26 00:00:00 1970 PST
 | |
|   386 |   6 | 00386              | Sat Mar 28 00:00:00 1970 PST
 | |
|   387 | 407 | 00387_update7      | Sun Mar 29 00:00:00 1970 PST
 | |
|   388 |   8 | 00388              | Mon Mar 30 00:00:00 1970 PST
 | |
|   389 | 509 | 00389_update9      | Tue Mar 31 00:00:00 1970 PST
 | |
|   390 |   0 | 00390              | Wed Apr 01 00:00:00 1970 PST
 | |
|   391 |   1 | 00391              | Thu Apr 02 00:00:00 1970 PST
 | |
|   393 | 303 | 00393_update3      | Sat Apr 04 00:00:00 1970 PST
 | |
|   394 |   4 | 00394              | Sun Apr 05 00:00:00 1970 PST
 | |
|   396 |   6 | 00396              | Tue Apr 07 00:00:00 1970 PST
 | |
|   397 | 407 | 00397_update7      | Wed Apr 08 00:00:00 1970 PST
 | |
|   398 |   8 | 00398              | Thu Apr 09 00:00:00 1970 PST
 | |
|   399 | 509 | 00399_update9      | Fri Apr 10 00:00:00 1970 PST
 | |
|   400 |   0 | 00400              | Thu Jan 01 00:00:00 1970 PST
 | |
|   401 |   1 | 00401              | Fri Jan 02 00:00:00 1970 PST
 | |
|   403 | 303 | 00403_update3      | Sun Jan 04 00:00:00 1970 PST
 | |
|   404 |   4 | 00404              | Mon Jan 05 00:00:00 1970 PST
 | |
|   406 |   6 | 00406              | Wed Jan 07 00:00:00 1970 PST
 | |
|   407 | 407 | 00407_update7      | Thu Jan 08 00:00:00 1970 PST
 | |
|   408 |   8 | 00408              | Fri Jan 09 00:00:00 1970 PST
 | |
|   409 | 509 | 00409_update9      | Sat Jan 10 00:00:00 1970 PST
 | |
|   410 |   0 | 00410              | Sun Jan 11 00:00:00 1970 PST
 | |
|   411 |   1 | 00411              | Mon Jan 12 00:00:00 1970 PST
 | |
|   413 | 303 | 00413_update3      | Wed Jan 14 00:00:00 1970 PST
 | |
|   414 |   4 | 00414              | Thu Jan 15 00:00:00 1970 PST
 | |
|   416 |   6 | 00416              | Sat Jan 17 00:00:00 1970 PST
 | |
|   417 | 407 | 00417_update7      | Sun Jan 18 00:00:00 1970 PST
 | |
|   418 |   8 | 00418              | Mon Jan 19 00:00:00 1970 PST
 | |
|   419 | 509 | 00419_update9      | Tue Jan 20 00:00:00 1970 PST
 | |
|   420 |   0 | 00420              | Wed Jan 21 00:00:00 1970 PST
 | |
|   421 |   1 | 00421              | Thu Jan 22 00:00:00 1970 PST
 | |
|   423 | 303 | 00423_update3      | Sat Jan 24 00:00:00 1970 PST
 | |
|   424 |   4 | 00424              | Sun Jan 25 00:00:00 1970 PST
 | |
|   426 |   6 | 00426              | Tue Jan 27 00:00:00 1970 PST
 | |
|   427 | 407 | 00427_update7      | Wed Jan 28 00:00:00 1970 PST
 | |
|   428 |   8 | 00428              | Thu Jan 29 00:00:00 1970 PST
 | |
|   429 | 509 | 00429_update9      | Fri Jan 30 00:00:00 1970 PST
 | |
|   430 |   0 | 00430              | Sat Jan 31 00:00:00 1970 PST
 | |
|   431 |   1 | 00431              | Sun Feb 01 00:00:00 1970 PST
 | |
|   433 | 303 | 00433_update3      | Tue Feb 03 00:00:00 1970 PST
 | |
|   434 |   4 | 00434              | Wed Feb 04 00:00:00 1970 PST
 | |
|   436 |   6 | 00436              | Fri Feb 06 00:00:00 1970 PST
 | |
|   437 | 407 | 00437_update7      | Sat Feb 07 00:00:00 1970 PST
 | |
|   438 |   8 | 00438              | Sun Feb 08 00:00:00 1970 PST
 | |
|   439 | 509 | 00439_update9      | Mon Feb 09 00:00:00 1970 PST
 | |
|   440 |   0 | 00440              | Tue Feb 10 00:00:00 1970 PST
 | |
|   441 |   1 | 00441              | Wed Feb 11 00:00:00 1970 PST
 | |
|   443 | 303 | 00443_update3      | Fri Feb 13 00:00:00 1970 PST
 | |
|   444 |   4 | 00444              | Sat Feb 14 00:00:00 1970 PST
 | |
|   446 |   6 | 00446              | Mon Feb 16 00:00:00 1970 PST
 | |
|   447 | 407 | 00447_update7      | Tue Feb 17 00:00:00 1970 PST
 | |
|   448 |   8 | 00448              | Wed Feb 18 00:00:00 1970 PST
 | |
|   449 | 509 | 00449_update9      | Thu Feb 19 00:00:00 1970 PST
 | |
|   450 |   0 | 00450              | Fri Feb 20 00:00:00 1970 PST
 | |
|   451 |   1 | 00451              | Sat Feb 21 00:00:00 1970 PST
 | |
|   453 | 303 | 00453_update3      | Mon Feb 23 00:00:00 1970 PST
 | |
|   454 |   4 | 00454              | Tue Feb 24 00:00:00 1970 PST
 | |
|   456 |   6 | 00456              | Thu Feb 26 00:00:00 1970 PST
 | |
|   457 | 407 | 00457_update7      | Fri Feb 27 00:00:00 1970 PST
 | |
|   458 |   8 | 00458              | Sat Feb 28 00:00:00 1970 PST
 | |
|   459 | 509 | 00459_update9      | Sun Mar 01 00:00:00 1970 PST
 | |
|   460 |   0 | 00460              | Mon Mar 02 00:00:00 1970 PST
 | |
|   461 |   1 | 00461              | Tue Mar 03 00:00:00 1970 PST
 | |
|   463 | 303 | 00463_update3      | Thu Mar 05 00:00:00 1970 PST
 | |
|   464 |   4 | 00464              | Fri Mar 06 00:00:00 1970 PST
 | |
|   466 |   6 | 00466              | Sun Mar 08 00:00:00 1970 PST
 | |
|   467 | 407 | 00467_update7      | Mon Mar 09 00:00:00 1970 PST
 | |
|   468 |   8 | 00468              | Tue Mar 10 00:00:00 1970 PST
 | |
|   469 | 509 | 00469_update9      | Wed Mar 11 00:00:00 1970 PST
 | |
|   470 |   0 | 00470              | Thu Mar 12 00:00:00 1970 PST
 | |
|   471 |   1 | 00471              | Fri Mar 13 00:00:00 1970 PST
 | |
|   473 | 303 | 00473_update3      | Sun Mar 15 00:00:00 1970 PST
 | |
|   474 |   4 | 00474              | Mon Mar 16 00:00:00 1970 PST
 | |
|   476 |   6 | 00476              | Wed Mar 18 00:00:00 1970 PST
 | |
|   477 | 407 | 00477_update7      | Thu Mar 19 00:00:00 1970 PST
 | |
|   478 |   8 | 00478              | Fri Mar 20 00:00:00 1970 PST
 | |
|   479 | 509 | 00479_update9      | Sat Mar 21 00:00:00 1970 PST
 | |
|   480 |   0 | 00480              | Sun Mar 22 00:00:00 1970 PST
 | |
|   481 |   1 | 00481              | Mon Mar 23 00:00:00 1970 PST
 | |
|   483 | 303 | 00483_update3      | Wed Mar 25 00:00:00 1970 PST
 | |
|   484 |   4 | 00484              | Thu Mar 26 00:00:00 1970 PST
 | |
|   486 |   6 | 00486              | Sat Mar 28 00:00:00 1970 PST
 | |
|   487 | 407 | 00487_update7      | Sun Mar 29 00:00:00 1970 PST
 | |
|   488 |   8 | 00488              | Mon Mar 30 00:00:00 1970 PST
 | |
|   489 | 509 | 00489_update9      | Tue Mar 31 00:00:00 1970 PST
 | |
|   490 |   0 | 00490              | Wed Apr 01 00:00:00 1970 PST
 | |
|   491 |   1 | 00491              | Thu Apr 02 00:00:00 1970 PST
 | |
|   493 | 303 | 00493_update3      | Sat Apr 04 00:00:00 1970 PST
 | |
|   494 |   4 | 00494              | Sun Apr 05 00:00:00 1970 PST
 | |
|   496 |   6 | 00496              | Tue Apr 07 00:00:00 1970 PST
 | |
|   497 | 407 | 00497_update7      | Wed Apr 08 00:00:00 1970 PST
 | |
|   498 |   8 | 00498              | Thu Apr 09 00:00:00 1970 PST
 | |
|   499 | 509 | 00499_update9      | Fri Apr 10 00:00:00 1970 PST
 | |
|   500 |   0 | 00500              | Thu Jan 01 00:00:00 1970 PST
 | |
|   501 |   1 | 00501              | Fri Jan 02 00:00:00 1970 PST
 | |
|   503 | 303 | 00503_update3      | Sun Jan 04 00:00:00 1970 PST
 | |
|   504 |   4 | 00504              | Mon Jan 05 00:00:00 1970 PST
 | |
|   506 |   6 | 00506              | Wed Jan 07 00:00:00 1970 PST
 | |
|   507 | 407 | 00507_update7      | Thu Jan 08 00:00:00 1970 PST
 | |
|   508 |   8 | 00508              | Fri Jan 09 00:00:00 1970 PST
 | |
|   509 | 509 | 00509_update9      | Sat Jan 10 00:00:00 1970 PST
 | |
|   510 |   0 | 00510              | Sun Jan 11 00:00:00 1970 PST
 | |
|   511 |   1 | 00511              | Mon Jan 12 00:00:00 1970 PST
 | |
|   513 | 303 | 00513_update3      | Wed Jan 14 00:00:00 1970 PST
 | |
|   514 |   4 | 00514              | Thu Jan 15 00:00:00 1970 PST
 | |
|   516 |   6 | 00516              | Sat Jan 17 00:00:00 1970 PST
 | |
|   517 | 407 | 00517_update7      | Sun Jan 18 00:00:00 1970 PST
 | |
|   518 |   8 | 00518              | Mon Jan 19 00:00:00 1970 PST
 | |
|   519 | 509 | 00519_update9      | Tue Jan 20 00:00:00 1970 PST
 | |
|   520 |   0 | 00520              | Wed Jan 21 00:00:00 1970 PST
 | |
|   521 |   1 | 00521              | Thu Jan 22 00:00:00 1970 PST
 | |
|   523 | 303 | 00523_update3      | Sat Jan 24 00:00:00 1970 PST
 | |
|   524 |   4 | 00524              | Sun Jan 25 00:00:00 1970 PST
 | |
|   526 |   6 | 00526              | Tue Jan 27 00:00:00 1970 PST
 | |
|   527 | 407 | 00527_update7      | Wed Jan 28 00:00:00 1970 PST
 | |
|   528 |   8 | 00528              | Thu Jan 29 00:00:00 1970 PST
 | |
|   529 | 509 | 00529_update9      | Fri Jan 30 00:00:00 1970 PST
 | |
|   530 |   0 | 00530              | Sat Jan 31 00:00:00 1970 PST
 | |
|   531 |   1 | 00531              | Sun Feb 01 00:00:00 1970 PST
 | |
|   533 | 303 | 00533_update3      | Tue Feb 03 00:00:00 1970 PST
 | |
|   534 |   4 | 00534              | Wed Feb 04 00:00:00 1970 PST
 | |
|   536 |   6 | 00536              | Fri Feb 06 00:00:00 1970 PST
 | |
|   537 | 407 | 00537_update7      | Sat Feb 07 00:00:00 1970 PST
 | |
|   538 |   8 | 00538              | Sun Feb 08 00:00:00 1970 PST
 | |
|   539 | 509 | 00539_update9      | Mon Feb 09 00:00:00 1970 PST
 | |
|   540 |   0 | 00540              | Tue Feb 10 00:00:00 1970 PST
 | |
|   541 |   1 | 00541              | Wed Feb 11 00:00:00 1970 PST
 | |
|   543 | 303 | 00543_update3      | Fri Feb 13 00:00:00 1970 PST
 | |
|   544 |   4 | 00544              | Sat Feb 14 00:00:00 1970 PST
 | |
|   546 |   6 | 00546              | Mon Feb 16 00:00:00 1970 PST
 | |
|   547 | 407 | 00547_update7      | Tue Feb 17 00:00:00 1970 PST
 | |
|   548 |   8 | 00548              | Wed Feb 18 00:00:00 1970 PST
 | |
|   549 | 509 | 00549_update9      | Thu Feb 19 00:00:00 1970 PST
 | |
|   550 |   0 | 00550              | Fri Feb 20 00:00:00 1970 PST
 | |
|   551 |   1 | 00551              | Sat Feb 21 00:00:00 1970 PST
 | |
|   553 | 303 | 00553_update3      | Mon Feb 23 00:00:00 1970 PST
 | |
|   554 |   4 | 00554              | Tue Feb 24 00:00:00 1970 PST
 | |
|   556 |   6 | 00556              | Thu Feb 26 00:00:00 1970 PST
 | |
|   557 | 407 | 00557_update7      | Fri Feb 27 00:00:00 1970 PST
 | |
|   558 |   8 | 00558              | Sat Feb 28 00:00:00 1970 PST
 | |
|   559 | 509 | 00559_update9      | Sun Mar 01 00:00:00 1970 PST
 | |
|   560 |   0 | 00560              | Mon Mar 02 00:00:00 1970 PST
 | |
|   561 |   1 | 00561              | Tue Mar 03 00:00:00 1970 PST
 | |
|   563 | 303 | 00563_update3      | Thu Mar 05 00:00:00 1970 PST
 | |
|   564 |   4 | 00564              | Fri Mar 06 00:00:00 1970 PST
 | |
|   566 |   6 | 00566              | Sun Mar 08 00:00:00 1970 PST
 | |
|   567 | 407 | 00567_update7      | Mon Mar 09 00:00:00 1970 PST
 | |
|   568 |   8 | 00568              | Tue Mar 10 00:00:00 1970 PST
 | |
|   569 | 509 | 00569_update9      | Wed Mar 11 00:00:00 1970 PST
 | |
|   570 |   0 | 00570              | Thu Mar 12 00:00:00 1970 PST
 | |
|   571 |   1 | 00571              | Fri Mar 13 00:00:00 1970 PST
 | |
|   573 | 303 | 00573_update3      | Sun Mar 15 00:00:00 1970 PST
 | |
|   574 |   4 | 00574              | Mon Mar 16 00:00:00 1970 PST
 | |
|   576 |   6 | 00576              | Wed Mar 18 00:00:00 1970 PST
 | |
|   577 | 407 | 00577_update7      | Thu Mar 19 00:00:00 1970 PST
 | |
|   578 |   8 | 00578              | Fri Mar 20 00:00:00 1970 PST
 | |
|   579 | 509 | 00579_update9      | Sat Mar 21 00:00:00 1970 PST
 | |
|   580 |   0 | 00580              | Sun Mar 22 00:00:00 1970 PST
 | |
|   581 |   1 | 00581              | Mon Mar 23 00:00:00 1970 PST
 | |
|   583 | 303 | 00583_update3      | Wed Mar 25 00:00:00 1970 PST
 | |
|   584 |   4 | 00584              | Thu Mar 26 00:00:00 1970 PST
 | |
|   586 |   6 | 00586              | Sat Mar 28 00:00:00 1970 PST
 | |
|   587 | 407 | 00587_update7      | Sun Mar 29 00:00:00 1970 PST
 | |
|   588 |   8 | 00588              | Mon Mar 30 00:00:00 1970 PST
 | |
|   589 | 509 | 00589_update9      | Tue Mar 31 00:00:00 1970 PST
 | |
|   590 |   0 | 00590              | Wed Apr 01 00:00:00 1970 PST
 | |
|   591 |   1 | 00591              | Thu Apr 02 00:00:00 1970 PST
 | |
|   593 | 303 | 00593_update3      | Sat Apr 04 00:00:00 1970 PST
 | |
|   594 |   4 | 00594              | Sun Apr 05 00:00:00 1970 PST
 | |
|   596 |   6 | 00596              | Tue Apr 07 00:00:00 1970 PST
 | |
|   597 | 407 | 00597_update7      | Wed Apr 08 00:00:00 1970 PST
 | |
|   598 |   8 | 00598              | Thu Apr 09 00:00:00 1970 PST
 | |
|   599 | 509 | 00599_update9      | Fri Apr 10 00:00:00 1970 PST
 | |
|   600 |   0 | 00600              | Thu Jan 01 00:00:00 1970 PST
 | |
|   601 |   1 | 00601              | Fri Jan 02 00:00:00 1970 PST
 | |
|   603 | 303 | 00603_update3      | Sun Jan 04 00:00:00 1970 PST
 | |
|   604 |   4 | 00604              | Mon Jan 05 00:00:00 1970 PST
 | |
|   606 |   6 | 00606              | Wed Jan 07 00:00:00 1970 PST
 | |
|   607 | 407 | 00607_update7      | Thu Jan 08 00:00:00 1970 PST
 | |
|   608 |   8 | 00608              | Fri Jan 09 00:00:00 1970 PST
 | |
|   609 | 509 | 00609_update9      | Sat Jan 10 00:00:00 1970 PST
 | |
|   610 |   0 | 00610              | Sun Jan 11 00:00:00 1970 PST
 | |
|   611 |   1 | 00611              | Mon Jan 12 00:00:00 1970 PST
 | |
|   613 | 303 | 00613_update3      | Wed Jan 14 00:00:00 1970 PST
 | |
|   614 |   4 | 00614              | Thu Jan 15 00:00:00 1970 PST
 | |
|   616 |   6 | 00616              | Sat Jan 17 00:00:00 1970 PST
 | |
|   617 | 407 | 00617_update7      | Sun Jan 18 00:00:00 1970 PST
 | |
|   618 |   8 | 00618              | Mon Jan 19 00:00:00 1970 PST
 | |
|   619 | 509 | 00619_update9      | Tue Jan 20 00:00:00 1970 PST
 | |
|   620 |   0 | 00620              | Wed Jan 21 00:00:00 1970 PST
 | |
|   621 |   1 | 00621              | Thu Jan 22 00:00:00 1970 PST
 | |
|   623 | 303 | 00623_update3      | Sat Jan 24 00:00:00 1970 PST
 | |
|   624 |   4 | 00624              | Sun Jan 25 00:00:00 1970 PST
 | |
|   626 |   6 | 00626              | Tue Jan 27 00:00:00 1970 PST
 | |
|   627 | 407 | 00627_update7      | Wed Jan 28 00:00:00 1970 PST
 | |
|   628 |   8 | 00628              | Thu Jan 29 00:00:00 1970 PST
 | |
|   629 | 509 | 00629_update9      | Fri Jan 30 00:00:00 1970 PST
 | |
|   630 |   0 | 00630              | Sat Jan 31 00:00:00 1970 PST
 | |
|   631 |   1 | 00631              | Sun Feb 01 00:00:00 1970 PST
 | |
|   633 | 303 | 00633_update3      | Tue Feb 03 00:00:00 1970 PST
 | |
|   634 |   4 | 00634              | Wed Feb 04 00:00:00 1970 PST
 | |
|   636 |   6 | 00636              | Fri Feb 06 00:00:00 1970 PST
 | |
|   637 | 407 | 00637_update7      | Sat Feb 07 00:00:00 1970 PST
 | |
|   638 |   8 | 00638              | Sun Feb 08 00:00:00 1970 PST
 | |
|   639 | 509 | 00639_update9      | Mon Feb 09 00:00:00 1970 PST
 | |
|   640 |   0 | 00640              | Tue Feb 10 00:00:00 1970 PST
 | |
|   641 |   1 | 00641              | Wed Feb 11 00:00:00 1970 PST
 | |
|   643 | 303 | 00643_update3      | Fri Feb 13 00:00:00 1970 PST
 | |
|   644 |   4 | 00644              | Sat Feb 14 00:00:00 1970 PST
 | |
|   646 |   6 | 00646              | Mon Feb 16 00:00:00 1970 PST
 | |
|   647 | 407 | 00647_update7      | Tue Feb 17 00:00:00 1970 PST
 | |
|   648 |   8 | 00648              | Wed Feb 18 00:00:00 1970 PST
 | |
|   649 | 509 | 00649_update9      | Thu Feb 19 00:00:00 1970 PST
 | |
|   650 |   0 | 00650              | Fri Feb 20 00:00:00 1970 PST
 | |
|   651 |   1 | 00651              | Sat Feb 21 00:00:00 1970 PST
 | |
|   653 | 303 | 00653_update3      | Mon Feb 23 00:00:00 1970 PST
 | |
|   654 |   4 | 00654              | Tue Feb 24 00:00:00 1970 PST
 | |
|   656 |   6 | 00656              | Thu Feb 26 00:00:00 1970 PST
 | |
|   657 | 407 | 00657_update7      | Fri Feb 27 00:00:00 1970 PST
 | |
|   658 |   8 | 00658              | Sat Feb 28 00:00:00 1970 PST
 | |
|   659 | 509 | 00659_update9      | Sun Mar 01 00:00:00 1970 PST
 | |
|   660 |   0 | 00660              | Mon Mar 02 00:00:00 1970 PST
 | |
|   661 |   1 | 00661              | Tue Mar 03 00:00:00 1970 PST
 | |
|   663 | 303 | 00663_update3      | Thu Mar 05 00:00:00 1970 PST
 | |
|   664 |   4 | 00664              | Fri Mar 06 00:00:00 1970 PST
 | |
|   666 |   6 | 00666              | Sun Mar 08 00:00:00 1970 PST
 | |
|   667 | 407 | 00667_update7      | Mon Mar 09 00:00:00 1970 PST
 | |
|   668 |   8 | 00668              | Tue Mar 10 00:00:00 1970 PST
 | |
|   669 | 509 | 00669_update9      | Wed Mar 11 00:00:00 1970 PST
 | |
|   670 |   0 | 00670              | Thu Mar 12 00:00:00 1970 PST
 | |
|   671 |   1 | 00671              | Fri Mar 13 00:00:00 1970 PST
 | |
|   673 | 303 | 00673_update3      | Sun Mar 15 00:00:00 1970 PST
 | |
|   674 |   4 | 00674              | Mon Mar 16 00:00:00 1970 PST
 | |
|   676 |   6 | 00676              | Wed Mar 18 00:00:00 1970 PST
 | |
|   677 | 407 | 00677_update7      | Thu Mar 19 00:00:00 1970 PST
 | |
|   678 |   8 | 00678              | Fri Mar 20 00:00:00 1970 PST
 | |
|   679 | 509 | 00679_update9      | Sat Mar 21 00:00:00 1970 PST
 | |
|   680 |   0 | 00680              | Sun Mar 22 00:00:00 1970 PST
 | |
|   681 |   1 | 00681              | Mon Mar 23 00:00:00 1970 PST
 | |
|   683 | 303 | 00683_update3      | Wed Mar 25 00:00:00 1970 PST
 | |
|   684 |   4 | 00684              | Thu Mar 26 00:00:00 1970 PST
 | |
|   686 |   6 | 00686              | Sat Mar 28 00:00:00 1970 PST
 | |
|   687 | 407 | 00687_update7      | Sun Mar 29 00:00:00 1970 PST
 | |
|   688 |   8 | 00688              | Mon Mar 30 00:00:00 1970 PST
 | |
|   689 | 509 | 00689_update9      | Tue Mar 31 00:00:00 1970 PST
 | |
|   690 |   0 | 00690              | Wed Apr 01 00:00:00 1970 PST
 | |
|   691 |   1 | 00691              | Thu Apr 02 00:00:00 1970 PST
 | |
|   693 | 303 | 00693_update3      | Sat Apr 04 00:00:00 1970 PST
 | |
|   694 |   4 | 00694              | Sun Apr 05 00:00:00 1970 PST
 | |
|   696 |   6 | 00696              | Tue Apr 07 00:00:00 1970 PST
 | |
|   697 | 407 | 00697_update7      | Wed Apr 08 00:00:00 1970 PST
 | |
|   698 |   8 | 00698              | Thu Apr 09 00:00:00 1970 PST
 | |
|   699 | 509 | 00699_update9      | Fri Apr 10 00:00:00 1970 PST
 | |
|   700 |   0 | 00700              | Thu Jan 01 00:00:00 1970 PST
 | |
|   701 |   1 | 00701              | Fri Jan 02 00:00:00 1970 PST
 | |
|   703 | 303 | 00703_update3      | Sun Jan 04 00:00:00 1970 PST
 | |
|   704 |   4 | 00704              | Mon Jan 05 00:00:00 1970 PST
 | |
|   706 |   6 | 00706              | Wed Jan 07 00:00:00 1970 PST
 | |
|   707 | 407 | 00707_update7      | Thu Jan 08 00:00:00 1970 PST
 | |
|   708 |   8 | 00708              | Fri Jan 09 00:00:00 1970 PST
 | |
|   709 | 509 | 00709_update9      | Sat Jan 10 00:00:00 1970 PST
 | |
|   710 |   0 | 00710              | Sun Jan 11 00:00:00 1970 PST
 | |
|   711 |   1 | 00711              | Mon Jan 12 00:00:00 1970 PST
 | |
|   713 | 303 | 00713_update3      | Wed Jan 14 00:00:00 1970 PST
 | |
|   714 |   4 | 00714              | Thu Jan 15 00:00:00 1970 PST
 | |
|   716 |   6 | 00716              | Sat Jan 17 00:00:00 1970 PST
 | |
|   717 | 407 | 00717_update7      | Sun Jan 18 00:00:00 1970 PST
 | |
|   718 |   8 | 00718              | Mon Jan 19 00:00:00 1970 PST
 | |
|   719 | 509 | 00719_update9      | Tue Jan 20 00:00:00 1970 PST
 | |
|   720 |   0 | 00720              | Wed Jan 21 00:00:00 1970 PST
 | |
|   721 |   1 | 00721              | Thu Jan 22 00:00:00 1970 PST
 | |
|   723 | 303 | 00723_update3      | Sat Jan 24 00:00:00 1970 PST
 | |
|   724 |   4 | 00724              | Sun Jan 25 00:00:00 1970 PST
 | |
|   726 |   6 | 00726              | Tue Jan 27 00:00:00 1970 PST
 | |
|   727 | 407 | 00727_update7      | Wed Jan 28 00:00:00 1970 PST
 | |
|   728 |   8 | 00728              | Thu Jan 29 00:00:00 1970 PST
 | |
|   729 | 509 | 00729_update9      | Fri Jan 30 00:00:00 1970 PST
 | |
|   730 |   0 | 00730              | Sat Jan 31 00:00:00 1970 PST
 | |
|   731 |   1 | 00731              | Sun Feb 01 00:00:00 1970 PST
 | |
|   733 | 303 | 00733_update3      | Tue Feb 03 00:00:00 1970 PST
 | |
|   734 |   4 | 00734              | Wed Feb 04 00:00:00 1970 PST
 | |
|   736 |   6 | 00736              | Fri Feb 06 00:00:00 1970 PST
 | |
|   737 | 407 | 00737_update7      | Sat Feb 07 00:00:00 1970 PST
 | |
|   738 |   8 | 00738              | Sun Feb 08 00:00:00 1970 PST
 | |
|   739 | 509 | 00739_update9      | Mon Feb 09 00:00:00 1970 PST
 | |
|   740 |   0 | 00740              | Tue Feb 10 00:00:00 1970 PST
 | |
|   741 |   1 | 00741              | Wed Feb 11 00:00:00 1970 PST
 | |
|   743 | 303 | 00743_update3      | Fri Feb 13 00:00:00 1970 PST
 | |
|   744 |   4 | 00744              | Sat Feb 14 00:00:00 1970 PST
 | |
|   746 |   6 | 00746              | Mon Feb 16 00:00:00 1970 PST
 | |
|   747 | 407 | 00747_update7      | Tue Feb 17 00:00:00 1970 PST
 | |
|   748 |   8 | 00748              | Wed Feb 18 00:00:00 1970 PST
 | |
|   749 | 509 | 00749_update9      | Thu Feb 19 00:00:00 1970 PST
 | |
|   750 |   0 | 00750              | Fri Feb 20 00:00:00 1970 PST
 | |
|   751 |   1 | 00751              | Sat Feb 21 00:00:00 1970 PST
 | |
|   753 | 303 | 00753_update3      | Mon Feb 23 00:00:00 1970 PST
 | |
|   754 |   4 | 00754              | Tue Feb 24 00:00:00 1970 PST
 | |
|   756 |   6 | 00756              | Thu Feb 26 00:00:00 1970 PST
 | |
|   757 | 407 | 00757_update7      | Fri Feb 27 00:00:00 1970 PST
 | |
|   758 |   8 | 00758              | Sat Feb 28 00:00:00 1970 PST
 | |
|   759 | 509 | 00759_update9      | Sun Mar 01 00:00:00 1970 PST
 | |
|   760 |   0 | 00760              | Mon Mar 02 00:00:00 1970 PST
 | |
|   761 |   1 | 00761              | Tue Mar 03 00:00:00 1970 PST
 | |
|   763 | 303 | 00763_update3      | Thu Mar 05 00:00:00 1970 PST
 | |
|   764 |   4 | 00764              | Fri Mar 06 00:00:00 1970 PST
 | |
|   766 |   6 | 00766              | Sun Mar 08 00:00:00 1970 PST
 | |
|   767 | 407 | 00767_update7      | Mon Mar 09 00:00:00 1970 PST
 | |
|   768 |   8 | 00768              | Tue Mar 10 00:00:00 1970 PST
 | |
|   769 | 509 | 00769_update9      | Wed Mar 11 00:00:00 1970 PST
 | |
|   770 |   0 | 00770              | Thu Mar 12 00:00:00 1970 PST
 | |
|   771 |   1 | 00771              | Fri Mar 13 00:00:00 1970 PST
 | |
|   773 | 303 | 00773_update3      | Sun Mar 15 00:00:00 1970 PST
 | |
|   774 |   4 | 00774              | Mon Mar 16 00:00:00 1970 PST
 | |
|   776 |   6 | 00776              | Wed Mar 18 00:00:00 1970 PST
 | |
|   777 | 407 | 00777_update7      | Thu Mar 19 00:00:00 1970 PST
 | |
|   778 |   8 | 00778              | Fri Mar 20 00:00:00 1970 PST
 | |
|   779 | 509 | 00779_update9      | Sat Mar 21 00:00:00 1970 PST
 | |
|   780 |   0 | 00780              | Sun Mar 22 00:00:00 1970 PST
 | |
|   781 |   1 | 00781              | Mon Mar 23 00:00:00 1970 PST
 | |
|   783 | 303 | 00783_update3      | Wed Mar 25 00:00:00 1970 PST
 | |
|   784 |   4 | 00784              | Thu Mar 26 00:00:00 1970 PST
 | |
|   786 |   6 | 00786              | Sat Mar 28 00:00:00 1970 PST
 | |
|   787 | 407 | 00787_update7      | Sun Mar 29 00:00:00 1970 PST
 | |
|   788 |   8 | 00788              | Mon Mar 30 00:00:00 1970 PST
 | |
|   789 | 509 | 00789_update9      | Tue Mar 31 00:00:00 1970 PST
 | |
|   790 |   0 | 00790              | Wed Apr 01 00:00:00 1970 PST
 | |
|   791 |   1 | 00791              | Thu Apr 02 00:00:00 1970 PST
 | |
|   793 | 303 | 00793_update3      | Sat Apr 04 00:00:00 1970 PST
 | |
|   794 |   4 | 00794              | Sun Apr 05 00:00:00 1970 PST
 | |
|   796 |   6 | 00796              | Tue Apr 07 00:00:00 1970 PST
 | |
|   797 | 407 | 00797_update7      | Wed Apr 08 00:00:00 1970 PST
 | |
|   798 |   8 | 00798              | Thu Apr 09 00:00:00 1970 PST
 | |
|   799 | 509 | 00799_update9      | Fri Apr 10 00:00:00 1970 PST
 | |
|   800 |   0 | 00800              | Thu Jan 01 00:00:00 1970 PST
 | |
|   801 |   1 | 00801              | Fri Jan 02 00:00:00 1970 PST
 | |
|   803 | 303 | 00803_update3      | Sun Jan 04 00:00:00 1970 PST
 | |
|   804 |   4 | 00804              | Mon Jan 05 00:00:00 1970 PST
 | |
|   806 |   6 | 00806              | Wed Jan 07 00:00:00 1970 PST
 | |
|   807 | 407 | 00807_update7      | Thu Jan 08 00:00:00 1970 PST
 | |
|   808 |   8 | 00808              | Fri Jan 09 00:00:00 1970 PST
 | |
|   809 | 509 | 00809_update9      | Sat Jan 10 00:00:00 1970 PST
 | |
|   810 |   0 | 00810              | Sun Jan 11 00:00:00 1970 PST
 | |
|   811 |   1 | 00811              | Mon Jan 12 00:00:00 1970 PST
 | |
|   813 | 303 | 00813_update3      | Wed Jan 14 00:00:00 1970 PST
 | |
|   814 |   4 | 00814              | Thu Jan 15 00:00:00 1970 PST
 | |
|   816 |   6 | 00816              | Sat Jan 17 00:00:00 1970 PST
 | |
|   817 | 407 | 00817_update7      | Sun Jan 18 00:00:00 1970 PST
 | |
|   818 |   8 | 00818              | Mon Jan 19 00:00:00 1970 PST
 | |
|   819 | 509 | 00819_update9      | Tue Jan 20 00:00:00 1970 PST
 | |
|   820 |   0 | 00820              | Wed Jan 21 00:00:00 1970 PST
 | |
|   821 |   1 | 00821              | Thu Jan 22 00:00:00 1970 PST
 | |
|   823 | 303 | 00823_update3      | Sat Jan 24 00:00:00 1970 PST
 | |
|   824 |   4 | 00824              | Sun Jan 25 00:00:00 1970 PST
 | |
|   826 |   6 | 00826              | Tue Jan 27 00:00:00 1970 PST
 | |
|   827 | 407 | 00827_update7      | Wed Jan 28 00:00:00 1970 PST
 | |
|   828 |   8 | 00828              | Thu Jan 29 00:00:00 1970 PST
 | |
|   829 | 509 | 00829_update9      | Fri Jan 30 00:00:00 1970 PST
 | |
|   830 |   0 | 00830              | Sat Jan 31 00:00:00 1970 PST
 | |
|   831 |   1 | 00831              | Sun Feb 01 00:00:00 1970 PST
 | |
|   833 | 303 | 00833_update3      | Tue Feb 03 00:00:00 1970 PST
 | |
|   834 |   4 | 00834              | Wed Feb 04 00:00:00 1970 PST
 | |
|   836 |   6 | 00836              | Fri Feb 06 00:00:00 1970 PST
 | |
|   837 | 407 | 00837_update7      | Sat Feb 07 00:00:00 1970 PST
 | |
|   838 |   8 | 00838              | Sun Feb 08 00:00:00 1970 PST
 | |
|   839 | 509 | 00839_update9      | Mon Feb 09 00:00:00 1970 PST
 | |
|   840 |   0 | 00840              | Tue Feb 10 00:00:00 1970 PST
 | |
|   841 |   1 | 00841              | Wed Feb 11 00:00:00 1970 PST
 | |
|   843 | 303 | 00843_update3      | Fri Feb 13 00:00:00 1970 PST
 | |
|   844 |   4 | 00844              | Sat Feb 14 00:00:00 1970 PST
 | |
|   846 |   6 | 00846              | Mon Feb 16 00:00:00 1970 PST
 | |
|   847 | 407 | 00847_update7      | Tue Feb 17 00:00:00 1970 PST
 | |
|   848 |   8 | 00848              | Wed Feb 18 00:00:00 1970 PST
 | |
|   849 | 509 | 00849_update9      | Thu Feb 19 00:00:00 1970 PST
 | |
|   850 |   0 | 00850              | Fri Feb 20 00:00:00 1970 PST
 | |
|   851 |   1 | 00851              | Sat Feb 21 00:00:00 1970 PST
 | |
|   853 | 303 | 00853_update3      | Mon Feb 23 00:00:00 1970 PST
 | |
|   854 |   4 | 00854              | Tue Feb 24 00:00:00 1970 PST
 | |
|   856 |   6 | 00856              | Thu Feb 26 00:00:00 1970 PST
 | |
|   857 | 407 | 00857_update7      | Fri Feb 27 00:00:00 1970 PST
 | |
|   858 |   8 | 00858              | Sat Feb 28 00:00:00 1970 PST
 | |
|   859 | 509 | 00859_update9      | Sun Mar 01 00:00:00 1970 PST
 | |
|   860 |   0 | 00860              | Mon Mar 02 00:00:00 1970 PST
 | |
|   861 |   1 | 00861              | Tue Mar 03 00:00:00 1970 PST
 | |
|   863 | 303 | 00863_update3      | Thu Mar 05 00:00:00 1970 PST
 | |
|   864 |   4 | 00864              | Fri Mar 06 00:00:00 1970 PST
 | |
|   866 |   6 | 00866              | Sun Mar 08 00:00:00 1970 PST
 | |
|   867 | 407 | 00867_update7      | Mon Mar 09 00:00:00 1970 PST
 | |
|   868 |   8 | 00868              | Tue Mar 10 00:00:00 1970 PST
 | |
|   869 | 509 | 00869_update9      | Wed Mar 11 00:00:00 1970 PST
 | |
|   870 |   0 | 00870              | Thu Mar 12 00:00:00 1970 PST
 | |
|   871 |   1 | 00871              | Fri Mar 13 00:00:00 1970 PST
 | |
|   873 | 303 | 00873_update3      | Sun Mar 15 00:00:00 1970 PST
 | |
|   874 |   4 | 00874              | Mon Mar 16 00:00:00 1970 PST
 | |
|   876 |   6 | 00876              | Wed Mar 18 00:00:00 1970 PST
 | |
|   877 | 407 | 00877_update7      | Thu Mar 19 00:00:00 1970 PST
 | |
|   878 |   8 | 00878              | Fri Mar 20 00:00:00 1970 PST
 | |
|   879 | 509 | 00879_update9      | Sat Mar 21 00:00:00 1970 PST
 | |
|   880 |   0 | 00880              | Sun Mar 22 00:00:00 1970 PST
 | |
|   881 |   1 | 00881              | Mon Mar 23 00:00:00 1970 PST
 | |
|   883 | 303 | 00883_update3      | Wed Mar 25 00:00:00 1970 PST
 | |
|   884 |   4 | 00884              | Thu Mar 26 00:00:00 1970 PST
 | |
|   886 |   6 | 00886              | Sat Mar 28 00:00:00 1970 PST
 | |
|   887 | 407 | 00887_update7      | Sun Mar 29 00:00:00 1970 PST
 | |
|   888 |   8 | 00888              | Mon Mar 30 00:00:00 1970 PST
 | |
|   889 | 509 | 00889_update9      | Tue Mar 31 00:00:00 1970 PST
 | |
|   890 |   0 | 00890              | Wed Apr 01 00:00:00 1970 PST
 | |
|   891 |   1 | 00891              | Thu Apr 02 00:00:00 1970 PST
 | |
|   893 | 303 | 00893_update3      | Sat Apr 04 00:00:00 1970 PST
 | |
|   894 |   4 | 00894              | Sun Apr 05 00:00:00 1970 PST
 | |
|   896 |   6 | 00896              | Tue Apr 07 00:00:00 1970 PST
 | |
|   897 | 407 | 00897_update7      | Wed Apr 08 00:00:00 1970 PST
 | |
|   898 |   8 | 00898              | Thu Apr 09 00:00:00 1970 PST
 | |
|   899 | 509 | 00899_update9      | Fri Apr 10 00:00:00 1970 PST
 | |
|   900 |   0 | 00900              | Thu Jan 01 00:00:00 1970 PST
 | |
|   901 |   1 | 00901              | Fri Jan 02 00:00:00 1970 PST
 | |
|   903 | 303 | 00903_update3      | Sun Jan 04 00:00:00 1970 PST
 | |
|   904 |   4 | 00904              | Mon Jan 05 00:00:00 1970 PST
 | |
|   906 |   6 | 00906              | Wed Jan 07 00:00:00 1970 PST
 | |
|   907 | 407 | 00907_update7      | Thu Jan 08 00:00:00 1970 PST
 | |
|   908 |   8 | 00908              | Fri Jan 09 00:00:00 1970 PST
 | |
|   909 | 509 | 00909_update9      | Sat Jan 10 00:00:00 1970 PST
 | |
|   910 |   0 | 00910              | Sun Jan 11 00:00:00 1970 PST
 | |
|   911 |   1 | 00911              | Mon Jan 12 00:00:00 1970 PST
 | |
|   913 | 303 | 00913_update3      | Wed Jan 14 00:00:00 1970 PST
 | |
|   914 |   4 | 00914              | Thu Jan 15 00:00:00 1970 PST
 | |
|   916 |   6 | 00916              | Sat Jan 17 00:00:00 1970 PST
 | |
|   917 | 407 | 00917_update7      | Sun Jan 18 00:00:00 1970 PST
 | |
|   918 |   8 | 00918              | Mon Jan 19 00:00:00 1970 PST
 | |
|   919 | 509 | 00919_update9      | Tue Jan 20 00:00:00 1970 PST
 | |
|   920 |   0 | 00920              | Wed Jan 21 00:00:00 1970 PST
 | |
|   921 |   1 | 00921              | Thu Jan 22 00:00:00 1970 PST
 | |
|   923 | 303 | 00923_update3      | Sat Jan 24 00:00:00 1970 PST
 | |
|   924 |   4 | 00924              | Sun Jan 25 00:00:00 1970 PST
 | |
|   926 |   6 | 00926              | Tue Jan 27 00:00:00 1970 PST
 | |
|   927 | 407 | 00927_update7      | Wed Jan 28 00:00:00 1970 PST
 | |
|   928 |   8 | 00928              | Thu Jan 29 00:00:00 1970 PST
 | |
|   929 | 509 | 00929_update9      | Fri Jan 30 00:00:00 1970 PST
 | |
|   930 |   0 | 00930              | Sat Jan 31 00:00:00 1970 PST
 | |
|   931 |   1 | 00931              | Sun Feb 01 00:00:00 1970 PST
 | |
|   933 | 303 | 00933_update3      | Tue Feb 03 00:00:00 1970 PST
 | |
|   934 |   4 | 00934              | Wed Feb 04 00:00:00 1970 PST
 | |
|   936 |   6 | 00936              | Fri Feb 06 00:00:00 1970 PST
 | |
|   937 | 407 | 00937_update7      | Sat Feb 07 00:00:00 1970 PST
 | |
|   938 |   8 | 00938              | Sun Feb 08 00:00:00 1970 PST
 | |
|   939 | 509 | 00939_update9      | Mon Feb 09 00:00:00 1970 PST
 | |
|   940 |   0 | 00940              | Tue Feb 10 00:00:00 1970 PST
 | |
|   941 |   1 | 00941              | Wed Feb 11 00:00:00 1970 PST
 | |
|   943 | 303 | 00943_update3      | Fri Feb 13 00:00:00 1970 PST
 | |
|   944 |   4 | 00944              | Sat Feb 14 00:00:00 1970 PST
 | |
|   946 |   6 | 00946              | Mon Feb 16 00:00:00 1970 PST
 | |
|   947 | 407 | 00947_update7      | Tue Feb 17 00:00:00 1970 PST
 | |
|   948 |   8 | 00948              | Wed Feb 18 00:00:00 1970 PST
 | |
|   949 | 509 | 00949_update9      | Thu Feb 19 00:00:00 1970 PST
 | |
|   950 |   0 | 00950              | Fri Feb 20 00:00:00 1970 PST
 | |
|   951 |   1 | 00951              | Sat Feb 21 00:00:00 1970 PST
 | |
|   953 | 303 | 00953_update3      | Mon Feb 23 00:00:00 1970 PST
 | |
|   954 |   4 | 00954              | Tue Feb 24 00:00:00 1970 PST
 | |
|   956 |   6 | 00956              | Thu Feb 26 00:00:00 1970 PST
 | |
|   957 | 407 | 00957_update7      | Fri Feb 27 00:00:00 1970 PST
 | |
|   958 |   8 | 00958              | Sat Feb 28 00:00:00 1970 PST
 | |
|   959 | 509 | 00959_update9      | Sun Mar 01 00:00:00 1970 PST
 | |
|   960 |   0 | 00960              | Mon Mar 02 00:00:00 1970 PST
 | |
|   961 |   1 | 00961              | Tue Mar 03 00:00:00 1970 PST
 | |
|   963 | 303 | 00963_update3      | Thu Mar 05 00:00:00 1970 PST
 | |
|   964 |   4 | 00964              | Fri Mar 06 00:00:00 1970 PST
 | |
|   966 |   6 | 00966              | Sun Mar 08 00:00:00 1970 PST
 | |
|   967 | 407 | 00967_update7      | Mon Mar 09 00:00:00 1970 PST
 | |
|   968 |   8 | 00968              | Tue Mar 10 00:00:00 1970 PST
 | |
|   969 | 509 | 00969_update9      | Wed Mar 11 00:00:00 1970 PST
 | |
|   970 |   0 | 00970              | Thu Mar 12 00:00:00 1970 PST
 | |
|   971 |   1 | 00971              | Fri Mar 13 00:00:00 1970 PST
 | |
|   973 | 303 | 00973_update3      | Sun Mar 15 00:00:00 1970 PST
 | |
|   974 |   4 | 00974              | Mon Mar 16 00:00:00 1970 PST
 | |
|   976 |   6 | 00976              | Wed Mar 18 00:00:00 1970 PST
 | |
|   977 | 407 | 00977_update7      | Thu Mar 19 00:00:00 1970 PST
 | |
|   978 |   8 | 00978              | Fri Mar 20 00:00:00 1970 PST
 | |
|   979 | 509 | 00979_update9      | Sat Mar 21 00:00:00 1970 PST
 | |
|   980 |   0 | 00980              | Sun Mar 22 00:00:00 1970 PST
 | |
|   981 |   1 | 00981              | Mon Mar 23 00:00:00 1970 PST
 | |
|   983 | 303 | 00983_update3      | Wed Mar 25 00:00:00 1970 PST
 | |
|   984 |   4 | 00984              | Thu Mar 26 00:00:00 1970 PST
 | |
|   986 |   6 | 00986              | Sat Mar 28 00:00:00 1970 PST
 | |
|   987 | 407 | 00987_update7      | Sun Mar 29 00:00:00 1970 PST
 | |
|   988 |   8 | 00988              | Mon Mar 30 00:00:00 1970 PST
 | |
|   989 | 509 | 00989_update9      | Tue Mar 31 00:00:00 1970 PST
 | |
|   990 |   0 | 00990              | Wed Apr 01 00:00:00 1970 PST
 | |
|   991 |   1 | 00991              | Thu Apr 02 00:00:00 1970 PST
 | |
|   993 | 303 | 00993_update3      | Sat Apr 04 00:00:00 1970 PST
 | |
|   994 |   4 | 00994              | Sun Apr 05 00:00:00 1970 PST
 | |
|   996 |   6 | 00996              | Tue Apr 07 00:00:00 1970 PST
 | |
|   997 | 407 | 00997_update7      | Wed Apr 08 00:00:00 1970 PST
 | |
|   998 |   8 | 00998              | Thu Apr 09 00:00:00 1970 PST
 | |
|   999 | 509 | 00999_update9      | Fri Apr 10 00:00:00 1970 PST
 | |
|  1000 |   0 | 01000              | Thu Jan 01 00:00:00 1970 PST
 | |
|  1001 | 101 | 0000100001         | 
 | |
|  1003 | 403 | 0000300003_update3 | 
 | |
|  1004 | 104 | 0000400004         | 
 | |
|  1006 | 106 | 0000600006         | 
 | |
|  1007 | 507 | 0000700007_update7 | 
 | |
|  1008 | 108 | 0000800008         | 
 | |
|  1009 | 609 | 0000900009_update9 | 
 | |
|  1010 | 100 | 0001000010         | 
 | |
|  1011 | 101 | 0001100011         | 
 | |
|  1013 | 403 | 0001300013_update3 | 
 | |
|  1014 | 104 | 0001400014         | 
 | |
|  1016 | 106 | 0001600016         | 
 | |
|  1017 | 507 | 0001700017_update7 | 
 | |
|  1018 | 108 | 0001800018         | 
 | |
|  1019 | 609 | 0001900019_update9 | 
 | |
|  1020 | 100 | 0002000020         | 
 | |
|  1101 | 201 | aaa                | 
 | |
|  1103 | 503 | ccc_update3        | 
 | |
|  1104 | 204 | ddd                | 
 | |
| (819 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| INSERT INTO ft2 (c1,c2,c3) VALUES (9999,999,'foo') RETURNING tableoid::regclass;
 | |
|                                                                                            QUERY PLAN                                                                                            
 | |
| -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
 | |
|  Insert on public.ft2
 | |
|    Output: (tableoid)::regclass
 | |
|    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)
 | |
|    ->  Result
 | |
|          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
 | |
| (5 rows)
 | |
| 
 | |
| INSERT INTO ft2 (c1,c2,c3) VALUES (9999,999,'foo') RETURNING tableoid::regclass;
 | |
|  tableoid 
 | |
| ----------
 | |
|  ft2
 | |
| (1 row)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE ft2 SET c3 = 'bar' WHERE c1 = 9999 RETURNING tableoid::regclass;             -- can be pushed down
 | |
|                                      QUERY PLAN                                     
 | |
| ------------------------------------------------------------------------------------
 | |
|  Update on public.ft2
 | |
|    Output: (tableoid)::regclass
 | |
|    ->  Foreign Update on public.ft2
 | |
|          Remote SQL: UPDATE "S 1"."T 1" SET c3 = 'bar'::text WHERE (("C 1" = 9999))
 | |
| (4 rows)
 | |
| 
 | |
| UPDATE ft2 SET c3 = 'bar' WHERE c1 = 9999 RETURNING tableoid::regclass;
 | |
|  tableoid 
 | |
| ----------
 | |
|  ft2
 | |
| (1 row)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| DELETE FROM ft2 WHERE c1 = 9999 RETURNING tableoid::regclass;                       -- can be pushed down
 | |
|                              QUERY PLAN                             
 | |
| --------------------------------------------------------------------
 | |
|  Delete on public.ft2
 | |
|    Output: (tableoid)::regclass
 | |
|    ->  Foreign Delete on public.ft2
 | |
|          Remote SQL: DELETE FROM "S 1"."T 1" WHERE (("C 1" = 9999))
 | |
| (4 rows)
 | |
| 
 | |
| DELETE FROM ft2 WHERE c1 = 9999 RETURNING tableoid::regclass;
 | |
|  tableoid 
 | |
| ----------
 | |
|  ft2
 | |
| (1 row)
 | |
| 
 | |
| -- Test that trigger on remote table works as expected
 | |
| CREATE OR REPLACE FUNCTION "S 1".F_BRTRIG() RETURNS trigger AS $$
 | |
| BEGIN
 | |
|     NEW.c3 = NEW.c3 || '_trig_update';
 | |
|     RETURN NEW;
 | |
| END;
 | |
| $$ LANGUAGE plpgsql;
 | |
| CREATE TRIGGER t1_br_insert BEFORE INSERT OR UPDATE
 | |
|     ON "S 1"."T 1" FOR EACH ROW EXECUTE PROCEDURE "S 1".F_BRTRIG();
 | |
| INSERT INTO ft2 (c1,c2,c3) VALUES (1208, 818, 'fff') RETURNING *;
 | |
|   c1  | c2  |       c3        | c4 | c5 | c6 |     c7     | c8 
 | |
| ------+-----+-----------------+----+----+----+------------+----
 | |
|  1208 | 818 | fff_trig_update |    |    |    | ft2        | 
 | |
| (1 row)
 | |
| 
 | |
| INSERT INTO ft2 (c1,c2,c3,c6) VALUES (1218, 818, 'ggg', '(--;') RETURNING *;
 | |
|   c1  | c2  |       c3        | c4 | c5 |  c6  |     c7     | c8 
 | |
| ------+-----+-----------------+----+----+------+------------+----
 | |
|  1218 | 818 | ggg_trig_update |    |    | (--; | ft2        | 
 | |
| (1 row)
 | |
| 
 | |
| UPDATE ft2 SET c2 = c2 + 600 WHERE c1 % 10 = 8 AND c1 < 1200 RETURNING *;
 | |
|   c1  | c2  |           c3           |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ------+-----+------------------------+------------------------------+--------------------------+----+------------+-----
 | |
|     8 | 608 | 00008_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|    18 | 608 | 00018_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
 | |
|    28 | 608 | 00028_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
 | |
|    38 | 608 | 00038_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
 | |
|    48 | 608 | 00048_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
 | |
|    58 | 608 | 00058_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
 | |
|    68 | 608 | 00068_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
 | |
|    78 | 608 | 00078_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
 | |
|    88 | 608 | 00088_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
 | |
|    98 | 608 | 00098_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   108 | 608 | 00108_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   118 | 608 | 00118_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
 | |
|   128 | 608 | 00128_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
 | |
|   138 | 608 | 00138_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
 | |
|   148 | 608 | 00148_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
 | |
|   158 | 608 | 00158_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
 | |
|   168 | 608 | 00168_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
 | |
|   178 | 608 | 00178_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
 | |
|   188 | 608 | 00188_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
 | |
|   198 | 608 | 00198_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   208 | 608 | 00208_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   218 | 608 | 00218_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
 | |
|   228 | 608 | 00228_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
 | |
|   238 | 608 | 00238_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
 | |
|   248 | 608 | 00248_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
 | |
|   258 | 608 | 00258_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
 | |
|   268 | 608 | 00268_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
 | |
|   278 | 608 | 00278_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
 | |
|   288 | 608 | 00288_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
 | |
|   298 | 608 | 00298_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   308 | 608 | 00308_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   318 | 608 | 00318_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
 | |
|   328 | 608 | 00328_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
 | |
|   338 | 608 | 00338_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
 | |
|   348 | 608 | 00348_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
 | |
|   358 | 608 | 00358_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
 | |
|   368 | 608 | 00368_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
 | |
|   378 | 608 | 00378_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
 | |
|   388 | 608 | 00388_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
 | |
|   398 | 608 | 00398_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   408 | 608 | 00408_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   418 | 608 | 00418_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
 | |
|   428 | 608 | 00428_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
 | |
|   438 | 608 | 00438_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
 | |
|   448 | 608 | 00448_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
 | |
|   458 | 608 | 00458_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
 | |
|   468 | 608 | 00468_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
 | |
|   478 | 608 | 00478_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
 | |
|   488 | 608 | 00488_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
 | |
|   498 | 608 | 00498_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   508 | 608 | 00508_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   518 | 608 | 00518_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
 | |
|   528 | 608 | 00528_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
 | |
|   538 | 608 | 00538_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
 | |
|   548 | 608 | 00548_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
 | |
|   558 | 608 | 00558_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
 | |
|   568 | 608 | 00568_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
 | |
|   578 | 608 | 00578_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
 | |
|   588 | 608 | 00588_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
 | |
|   598 | 608 | 00598_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   608 | 608 | 00608_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   618 | 608 | 00618_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
 | |
|   628 | 608 | 00628_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
 | |
|   638 | 608 | 00638_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
 | |
|   648 | 608 | 00648_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
 | |
|   658 | 608 | 00658_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
 | |
|   668 | 608 | 00668_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
 | |
|   678 | 608 | 00678_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
 | |
|   688 | 608 | 00688_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
 | |
|   698 | 608 | 00698_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   708 | 608 | 00708_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   718 | 608 | 00718_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
 | |
|   728 | 608 | 00728_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
 | |
|   738 | 608 | 00738_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
 | |
|   748 | 608 | 00748_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
 | |
|   758 | 608 | 00758_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
 | |
|   768 | 608 | 00768_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
 | |
|   778 | 608 | 00778_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
 | |
|   788 | 608 | 00788_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
 | |
|   798 | 608 | 00798_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   808 | 608 | 00808_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   818 | 608 | 00818_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
 | |
|   828 | 608 | 00828_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
 | |
|   838 | 608 | 00838_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
 | |
|   848 | 608 | 00848_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
 | |
|   858 | 608 | 00858_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
 | |
|   868 | 608 | 00868_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
 | |
|   878 | 608 | 00878_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
 | |
|   888 | 608 | 00888_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
 | |
|   898 | 608 | 00898_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   908 | 608 | 00908_trig_update      | Fri Jan 09 00:00:00 1970 PST | Fri Jan 09 00:00:00 1970 | 8  | 8          | foo
 | |
|   918 | 608 | 00918_trig_update      | Mon Jan 19 00:00:00 1970 PST | Mon Jan 19 00:00:00 1970 | 8  | 8          | foo
 | |
|   928 | 608 | 00928_trig_update      | Thu Jan 29 00:00:00 1970 PST | Thu Jan 29 00:00:00 1970 | 8  | 8          | foo
 | |
|   938 | 608 | 00938_trig_update      | Sun Feb 08 00:00:00 1970 PST | Sun Feb 08 00:00:00 1970 | 8  | 8          | foo
 | |
|   948 | 608 | 00948_trig_update      | Wed Feb 18 00:00:00 1970 PST | Wed Feb 18 00:00:00 1970 | 8  | 8          | foo
 | |
|   958 | 608 | 00958_trig_update      | Sat Feb 28 00:00:00 1970 PST | Sat Feb 28 00:00:00 1970 | 8  | 8          | foo
 | |
|   968 | 608 | 00968_trig_update      | Tue Mar 10 00:00:00 1970 PST | Tue Mar 10 00:00:00 1970 | 8  | 8          | foo
 | |
|   978 | 608 | 00978_trig_update      | Fri Mar 20 00:00:00 1970 PST | Fri Mar 20 00:00:00 1970 | 8  | 8          | foo
 | |
|   988 | 608 | 00988_trig_update      | Mon Mar 30 00:00:00 1970 PST | Mon Mar 30 00:00:00 1970 | 8  | 8          | foo
 | |
|   998 | 608 | 00998_trig_update      | Thu Apr 09 00:00:00 1970 PST | Thu Apr 09 00:00:00 1970 | 8  | 8          | foo
 | |
|  1008 | 708 | 0000800008_trig_update |                              |                          |    | ft2        | 
 | |
|  1018 | 708 | 0001800018_trig_update |                              |                          |    | ft2        | 
 | |
| (102 rows)
 | |
| 
 | |
| -- Test errors thrown on remote side during update
 | |
| ALTER TABLE "S 1"."T 1" ADD CONSTRAINT c2positive CHECK (c2 >= 0);
 | |
| INSERT INTO ft1(c1, c2) VALUES(11, 12);  -- duplicate key
 | |
| ERROR:  duplicate key value violates unique constraint "t1_pkey"
 | |
| DETAIL:  Key ("C 1")=(11) already exists.
 | |
| 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)
 | |
| INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT DO NOTHING; -- works
 | |
| INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO NOTHING; -- unsupported
 | |
| ERROR:  there is no unique or exclusion constraint matching the ON CONFLICT specification
 | |
| INSERT INTO ft1(c1, c2) VALUES(11, 12) ON CONFLICT (c1, c2) DO UPDATE SET c3 = 'ffg'; -- unsupported
 | |
| ERROR:  there is no unique or exclusion constraint matching the ON CONFLICT specification
 | |
| INSERT INTO ft1(c1, c2) VALUES(1111, -2);  -- c2positive
 | |
| ERROR:  new row for relation "T 1" violates check constraint "c2positive"
 | |
| DETAIL:  Failing row contains (1111, -2, null, null, null, null, ft1       , null).
 | |
| 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)
 | |
| UPDATE ft1 SET c2 = -c2 WHERE c1 = 1;  -- c2positive
 | |
| ERROR:  new row for relation "T 1" violates check constraint "c2positive"
 | |
| 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).
 | |
| CONTEXT:  Remote SQL command: UPDATE "S 1"."T 1" SET c2 = (- c2) WHERE (("C 1" = 1))
 | |
| -- Test savepoint/rollback behavior
 | |
| select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    0 |   100
 | |
|    1 |   100
 | |
|    4 |   100
 | |
|    6 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    0 |   100
 | |
|    1 |   100
 | |
|    4 |   100
 | |
|    6 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| begin;
 | |
| update ft2 set c2 = 42 where c2 = 0;
 | |
| select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    1 |   100
 | |
|    4 |   100
 | |
|    6 |   100
 | |
|   42 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| savepoint s1;
 | |
| update ft2 set c2 = 44 where c2 = 4;
 | |
| select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    1 |   100
 | |
|    6 |   100
 | |
|   42 |   100
 | |
|   44 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| release savepoint s1;
 | |
| select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    1 |   100
 | |
|    6 |   100
 | |
|   42 |   100
 | |
|   44 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| savepoint s2;
 | |
| update ft2 set c2 = 46 where c2 = 6;
 | |
| select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    1 |   100
 | |
|   42 |   100
 | |
|   44 |   100
 | |
|   46 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| rollback to savepoint s2;
 | |
| select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    1 |   100
 | |
|    6 |   100
 | |
|   42 |   100
 | |
|   44 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| release savepoint s2;
 | |
| select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    1 |   100
 | |
|    6 |   100
 | |
|   42 |   100
 | |
|   44 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| savepoint s3;
 | |
| update ft2 set c2 = -2 where c2 = 42 and c1 = 10; -- fail on remote side
 | |
| ERROR:  new row for relation "T 1" violates check constraint "c2positive"
 | |
| 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).
 | |
| CONTEXT:  Remote SQL command: UPDATE "S 1"."T 1" SET c2 = (-2) WHERE ((c2 = 42)) AND (("C 1" = 10))
 | |
| rollback to savepoint s3;
 | |
| select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    1 |   100
 | |
|    6 |   100
 | |
|   42 |   100
 | |
|   44 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| release savepoint s3;
 | |
| select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    1 |   100
 | |
|    6 |   100
 | |
|   42 |   100
 | |
|   44 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| -- none of the above is committed yet remotely
 | |
| select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    0 |   100
 | |
|    1 |   100
 | |
|    4 |   100
 | |
|    6 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| commit;
 | |
| select c2, count(*) from ft2 where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    1 |   100
 | |
|    6 |   100
 | |
|   42 |   100
 | |
|   44 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
 | |
|  c2  | count 
 | |
| -----+-------
 | |
|    1 |   100
 | |
|    6 |   100
 | |
|   42 |   100
 | |
|   44 |   100
 | |
|  100 |     2
 | |
|  101 |     2
 | |
|  104 |     2
 | |
|  106 |     2
 | |
|  201 |     1
 | |
|  204 |     1
 | |
|  303 |   100
 | |
|  403 |     2
 | |
|  407 |   100
 | |
| (13 rows)
 | |
| 
 | |
| -- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs
 | |
| -- FIRST behavior here.
 | |
| -- ORDER BY DESC NULLS LAST options
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795 LIMIT 10;
 | |
|                                                            QUERY PLAN                                                            
 | |
| ---------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    ->  Foreign Scan on public.ft1
 | |
|          Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|          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
 | |
| (5 rows)
 | |
| 
 | |
| SELECT * FROM ft1 ORDER BY c6 DESC NULLS LAST, c1 OFFSET 795  LIMIT 10;
 | |
|   c1  | c2  |         c3         |              c4              |            c5            |  c6  |     c7     | c8  
 | |
| ------+-----+--------------------+------------------------------+--------------------------+------+------------+-----
 | |
|   960 |  42 | 00960_trig_update  | Mon Mar 02 00:00:00 1970 PST | Mon Mar 02 00:00:00 1970 | 0    | 0          | foo
 | |
|   970 |  42 | 00970_trig_update  | Thu Mar 12 00:00:00 1970 PST | Thu Mar 12 00:00:00 1970 | 0    | 0          | foo
 | |
|   980 |  42 | 00980_trig_update  | Sun Mar 22 00:00:00 1970 PST | Sun Mar 22 00:00:00 1970 | 0    | 0          | foo
 | |
|   990 |  42 | 00990_trig_update  | Wed Apr 01 00:00:00 1970 PST | Wed Apr 01 00:00:00 1970 | 0    | 0          | foo
 | |
|  1000 |  42 | 01000_trig_update  | Thu Jan 01 00:00:00 1970 PST | Thu Jan 01 00:00:00 1970 | 0    | 0          | foo
 | |
|  1218 | 818 | ggg_trig_update    |                              |                          | (--; | ft2        | 
 | |
|  1001 | 101 | 0000100001         |                              |                          |      | ft2        | 
 | |
|  1003 | 403 | 0000300003_update3 |                              |                          |      | ft2        | 
 | |
|  1004 | 104 | 0000400004         |                              |                          |      | ft2        | 
 | |
|  1006 | 106 | 0000600006         |                              |                          |      | ft2        | 
 | |
| (10 rows)
 | |
| 
 | |
| -- ORDER BY DESC NULLS FIRST options
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
 | |
|                                                             QUERY PLAN                                                            
 | |
| ----------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    ->  Foreign Scan on public.ft1
 | |
|          Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|          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
 | |
| (5 rows)
 | |
| 
 | |
| SELECT * FROM ft1 ORDER BY c6 DESC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
 | |
|   c1  | c2  |       c3        |              c4              |            c5            | c6 |     c7     | c8  
 | |
| ------+-----+-----------------+------------------------------+--------------------------+----+------------+-----
 | |
|  1020 | 100 | 0002000020      |                              |                          |    | ft2        | 
 | |
|  1101 | 201 | aaa             |                              |                          |    | ft2        | 
 | |
|  1103 | 503 | ccc_update3     |                              |                          |    | ft2        | 
 | |
|  1104 | 204 | ddd             |                              |                          |    | ft2        | 
 | |
|  1208 | 818 | fff_trig_update |                              |                          |    | ft2        | 
 | |
|     9 | 509 | 00009_update9   | Sat Jan 10 00:00:00 1970 PST | Sat Jan 10 00:00:00 1970 | 9  | ft2        | foo
 | |
|    19 | 509 | 00019_update9   | Tue Jan 20 00:00:00 1970 PST | Tue Jan 20 00:00:00 1970 | 9  | ft2        | foo
 | |
|    29 | 509 | 00029_update9   | Fri Jan 30 00:00:00 1970 PST | Fri Jan 30 00:00:00 1970 | 9  | ft2        | foo
 | |
|    39 | 509 | 00039_update9   | Mon Feb 09 00:00:00 1970 PST | Mon Feb 09 00:00:00 1970 | 9  | ft2        | foo
 | |
|    49 | 509 | 00049_update9   | Thu Feb 19 00:00:00 1970 PST | Thu Feb 19 00:00:00 1970 | 9  | ft2        | foo
 | |
| (10 rows)
 | |
| 
 | |
| -- ORDER BY ASC NULLS FIRST options
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
 | |
|                                                            QUERY PLAN                                                            
 | |
| ---------------------------------------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|    ->  Foreign Scan on public.ft1
 | |
|          Output: c1, c2, c3, c4, c5, c6, c7, c8
 | |
|          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
 | |
| (5 rows)
 | |
| 
 | |
| SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
 | |
|   c1  | c2  |        c3         |              c4              |            c5            |  c6  |     c7     | c8  
 | |
| ------+-----+-------------------+------------------------------+--------------------------+------+------------+-----
 | |
|  1020 | 100 | 0002000020        |                              |                          |      | ft2        | 
 | |
|  1101 | 201 | aaa               |                              |                          |      | ft2        | 
 | |
|  1103 | 503 | ccc_update3       |                              |                          |      | ft2        | 
 | |
|  1104 | 204 | ddd               |                              |                          |      | ft2        | 
 | |
|  1208 | 818 | fff_trig_update   |                              |                          |      | ft2        | 
 | |
|  1218 | 818 | ggg_trig_update   |                              |                          | (--; | ft2        | 
 | |
|    10 |  42 | 00010_trig_update | Sun Jan 11 00:00:00 1970 PST | Sun Jan 11 00:00:00 1970 | 0    | 0          | foo
 | |
|    20 |  42 | 00020_trig_update | Wed Jan 21 00:00:00 1970 PST | Wed Jan 21 00:00:00 1970 | 0    | 0          | foo
 | |
|    30 |  42 | 00030_trig_update | Sat Jan 31 00:00:00 1970 PST | Sat Jan 31 00:00:00 1970 | 0    | 0          | foo
 | |
|    40 |  42 | 00040_trig_update | Tue Feb 10 00:00:00 1970 PST | Tue Feb 10 00:00:00 1970 | 0    | 0          | foo
 | |
| (10 rows)
 | |
| 
 | |
| -- ===================================================================
 | |
| -- test check constraints
 | |
| -- ===================================================================
 | |
| -- Consistent check constraints provide consistent results
 | |
| ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK (c2 >= 0);
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0;
 | |
|                            QUERY PLAN                            
 | |
| -----------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: (count(*))
 | |
|    Relations: Aggregate on (public.ft1)
 | |
|    Remote SQL: SELECT count(*) FROM "S 1"."T 1" WHERE ((c2 < 0))
 | |
| (4 rows)
 | |
| 
 | |
| SELECT count(*) FROM ft1 WHERE c2 < 0;
 | |
|  count 
 | |
| -------
 | |
|      0
 | |
| (1 row)
 | |
| 
 | |
| SET constraint_exclusion = 'on';
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 < 0;
 | |
|            QUERY PLAN           
 | |
| --------------------------------
 | |
|  Aggregate
 | |
|    Output: count(*)
 | |
|    ->  Result
 | |
|          One-Time Filter: false
 | |
| (4 rows)
 | |
| 
 | |
| SELECT count(*) FROM ft1 WHERE c2 < 0;
 | |
|  count 
 | |
| -------
 | |
|      0
 | |
| (1 row)
 | |
| 
 | |
| RESET constraint_exclusion;
 | |
| -- check constraint is enforced on the remote side, not locally
 | |
| INSERT INTO ft1(c1, c2) VALUES(1111, -2);  -- c2positive
 | |
| ERROR:  new row for relation "T 1" violates check constraint "c2positive"
 | |
| DETAIL:  Failing row contains (1111, -2, null, null, null, null, ft1       , null).
 | |
| 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)
 | |
| UPDATE ft1 SET c2 = -c2 WHERE c1 = 1;  -- c2positive
 | |
| ERROR:  new row for relation "T 1" violates check constraint "c2positive"
 | |
| 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).
 | |
| CONTEXT:  Remote SQL command: UPDATE "S 1"."T 1" SET c2 = (- c2) WHERE (("C 1" = 1))
 | |
| ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive;
 | |
| -- But inconsistent check constraints provide inconsistent results
 | |
| ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK (c2 < 0);
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0;
 | |
|                             QUERY PLAN                            
 | |
| ------------------------------------------------------------------
 | |
|  Foreign Scan
 | |
|    Output: (count(*))
 | |
|    Relations: Aggregate on (public.ft1)
 | |
|    Remote SQL: SELECT count(*) FROM "S 1"."T 1" WHERE ((c2 >= 0))
 | |
| (4 rows)
 | |
| 
 | |
| SELECT count(*) FROM ft1 WHERE c2 >= 0;
 | |
|  count 
 | |
| -------
 | |
|    821
 | |
| (1 row)
 | |
| 
 | |
| SET constraint_exclusion = 'on';
 | |
| EXPLAIN (VERBOSE, COSTS OFF) SELECT count(*) FROM ft1 WHERE c2 >= 0;
 | |
|            QUERY PLAN           
 | |
| --------------------------------
 | |
|  Aggregate
 | |
|    Output: count(*)
 | |
|    ->  Result
 | |
|          One-Time Filter: false
 | |
| (4 rows)
 | |
| 
 | |
| SELECT count(*) FROM ft1 WHERE c2 >= 0;
 | |
|  count 
 | |
| -------
 | |
|      0
 | |
| (1 row)
 | |
| 
 | |
| RESET constraint_exclusion;
 | |
| -- local check constraint is not actually enforced
 | |
| INSERT INTO ft1(c1, c2) VALUES(1111, 2);
 | |
| UPDATE ft1 SET c2 = c2 + 1 WHERE c1 = 1;
 | |
| ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2negative;
 | |
| -- ===================================================================
 | |
| -- test serial columns (ie, sequence-based defaults)
 | |
| -- ===================================================================
 | |
| create table loc1 (f1 serial, f2 text);
 | |
| create foreign table rem1 (f1 serial, f2 text)
 | |
|   server loopback options(table_name 'loc1');
 | |
| select pg_catalog.setval('rem1_f1_seq', 10, false);
 | |
|  setval 
 | |
| --------
 | |
|      10
 | |
| (1 row)
 | |
| 
 | |
| insert into loc1(f2) values('hi');
 | |
| insert into rem1(f2) values('hi remote');
 | |
| insert into loc1(f2) values('bye');
 | |
| insert into rem1(f2) values('bye remote');
 | |
| select * from loc1;
 | |
|  f1 |     f2     
 | |
| ----+------------
 | |
|   1 | hi
 | |
|  10 | hi remote
 | |
|   2 | bye
 | |
|  11 | bye remote
 | |
| (4 rows)
 | |
| 
 | |
| select * from rem1;
 | |
|  f1 |     f2     
 | |
| ----+------------
 | |
|   1 | hi
 | |
|  10 | hi remote
 | |
|   2 | bye
 | |
|  11 | bye remote
 | |
| (4 rows)
 | |
| 
 | |
| -- ===================================================================
 | |
| -- test local triggers
 | |
| -- ===================================================================
 | |
| -- Trigger functions "borrowed" from triggers regress test.
 | |
| CREATE FUNCTION trigger_func() RETURNS trigger LANGUAGE plpgsql AS $$
 | |
| BEGIN
 | |
| 	RAISE NOTICE 'trigger_func(%) called: action = %, when = %, level = %',
 | |
| 		TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL;
 | |
| 	RETURN NULL;
 | |
| END;$$;
 | |
| CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE ON rem1
 | |
| 	FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
 | |
| CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE ON rem1
 | |
| 	FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
 | |
| CREATE OR REPLACE FUNCTION trigger_data()  RETURNS trigger
 | |
| LANGUAGE plpgsql AS $$
 | |
| 
 | |
| declare
 | |
| 	oldnew text[];
 | |
| 	relid text;
 | |
|     argstr text;
 | |
| begin
 | |
| 
 | |
| 	relid := TG_relid::regclass;
 | |
| 	argstr := '';
 | |
| 	for i in 0 .. TG_nargs - 1 loop
 | |
| 		if i > 0 then
 | |
| 			argstr := argstr || ', ';
 | |
| 		end if;
 | |
| 		argstr := argstr || TG_argv[i];
 | |
| 	end loop;
 | |
| 
 | |
|     RAISE NOTICE '%(%) % % % ON %',
 | |
| 		tg_name, argstr, TG_when, TG_level, TG_OP, relid;
 | |
|     oldnew := '{}'::text[];
 | |
| 	if TG_OP != 'INSERT' then
 | |
| 		oldnew := array_append(oldnew, format('OLD: %s', OLD));
 | |
| 	end if;
 | |
| 
 | |
| 	if TG_OP != 'DELETE' then
 | |
| 		oldnew := array_append(oldnew, format('NEW: %s', NEW));
 | |
| 	end if;
 | |
| 
 | |
|     RAISE NOTICE '%', array_to_string(oldnew, ',');
 | |
| 
 | |
| 	if TG_OP = 'DELETE' then
 | |
| 		return OLD;
 | |
| 	else
 | |
| 		return NEW;
 | |
| 	end if;
 | |
| end;
 | |
| $$;
 | |
| -- Test basic functionality
 | |
| CREATE TRIGGER trig_row_before
 | |
| BEFORE INSERT OR UPDATE OR DELETE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| CREATE TRIGGER trig_row_after
 | |
| AFTER INSERT OR UPDATE OR DELETE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| delete from rem1;
 | |
| NOTICE:  trigger_func(<NULL>) called: action = DELETE, when = BEFORE, level = STATEMENT
 | |
| NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
 | |
| NOTICE:  OLD: (1,hi)
 | |
| NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
 | |
| NOTICE:  OLD: (10,"hi remote")
 | |
| NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
 | |
| NOTICE:  OLD: (2,bye)
 | |
| NOTICE:  trig_row_before(23, skidoo) BEFORE ROW DELETE ON rem1
 | |
| NOTICE:  OLD: (11,"bye remote")
 | |
| NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
 | |
| NOTICE:  OLD: (1,hi)
 | |
| NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
 | |
| NOTICE:  OLD: (10,"hi remote")
 | |
| NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
 | |
| NOTICE:  OLD: (2,bye)
 | |
| NOTICE:  trig_row_after(23, skidoo) AFTER ROW DELETE ON rem1
 | |
| NOTICE:  OLD: (11,"bye remote")
 | |
| NOTICE:  trigger_func(<NULL>) called: action = DELETE, when = AFTER, level = STATEMENT
 | |
| insert into rem1 values(1,'insert');
 | |
| NOTICE:  trigger_func(<NULL>) called: action = INSERT, when = BEFORE, level = STATEMENT
 | |
| NOTICE:  trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
 | |
| NOTICE:  NEW: (1,insert)
 | |
| NOTICE:  trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
 | |
| NOTICE:  NEW: (1,insert)
 | |
| NOTICE:  trigger_func(<NULL>) called: action = INSERT, when = AFTER, level = STATEMENT
 | |
| update rem1 set f2  = 'update' where f1 = 1;
 | |
| NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = BEFORE, level = STATEMENT
 | |
| NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
 | |
| NOTICE:  OLD: (1,insert),NEW: (1,update)
 | |
| NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
 | |
| NOTICE:  OLD: (1,insert),NEW: (1,update)
 | |
| NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
 | |
| update rem1 set f2 = f2 || f2;
 | |
| NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = BEFORE, level = STATEMENT
 | |
| NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
 | |
| NOTICE:  OLD: (1,update),NEW: (1,updateupdate)
 | |
| NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
 | |
| NOTICE:  OLD: (1,update),NEW: (1,updateupdate)
 | |
| NOTICE:  trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
 | |
| -- cleanup
 | |
| DROP TRIGGER trig_row_before ON rem1;
 | |
| DROP TRIGGER trig_row_after ON rem1;
 | |
| DROP TRIGGER trig_stmt_before ON rem1;
 | |
| DROP TRIGGER trig_stmt_after ON rem1;
 | |
| DELETE from rem1;
 | |
| -- Test WHEN conditions
 | |
| CREATE TRIGGER trig_row_before_insupd
 | |
| BEFORE INSERT OR UPDATE ON rem1
 | |
| FOR EACH ROW
 | |
| WHEN (NEW.f2 like '%update%')
 | |
| EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| CREATE TRIGGER trig_row_after_insupd
 | |
| AFTER INSERT OR UPDATE ON rem1
 | |
| FOR EACH ROW
 | |
| WHEN (NEW.f2 like '%update%')
 | |
| EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| -- Insert or update not matching: nothing happens
 | |
| INSERT INTO rem1 values(1, 'insert');
 | |
| UPDATE rem1 set f2 = 'test';
 | |
| -- Insert or update matching: triggers are fired
 | |
| INSERT INTO rem1 values(2, 'update');
 | |
| NOTICE:  trig_row_before_insupd(23, skidoo) BEFORE ROW INSERT ON rem1
 | |
| NOTICE:  NEW: (2,update)
 | |
| NOTICE:  trig_row_after_insupd(23, skidoo) AFTER ROW INSERT ON rem1
 | |
| NOTICE:  NEW: (2,update)
 | |
| UPDATE rem1 set f2 = 'update update' where f1 = '2';
 | |
| NOTICE:  trig_row_before_insupd(23, skidoo) BEFORE ROW UPDATE ON rem1
 | |
| NOTICE:  OLD: (2,update),NEW: (2,"update update")
 | |
| NOTICE:  trig_row_after_insupd(23, skidoo) AFTER ROW UPDATE ON rem1
 | |
| NOTICE:  OLD: (2,update),NEW: (2,"update update")
 | |
| CREATE TRIGGER trig_row_before_delete
 | |
| BEFORE DELETE ON rem1
 | |
| FOR EACH ROW
 | |
| WHEN (OLD.f2 like '%update%')
 | |
| EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| CREATE TRIGGER trig_row_after_delete
 | |
| AFTER DELETE ON rem1
 | |
| FOR EACH ROW
 | |
| WHEN (OLD.f2 like '%update%')
 | |
| EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| -- Trigger is fired for f1=2, not for f1=1
 | |
| DELETE FROM rem1;
 | |
| NOTICE:  trig_row_before_delete(23, skidoo) BEFORE ROW DELETE ON rem1
 | |
| NOTICE:  OLD: (2,"update update")
 | |
| NOTICE:  trig_row_after_delete(23, skidoo) AFTER ROW DELETE ON rem1
 | |
| NOTICE:  OLD: (2,"update update")
 | |
| -- cleanup
 | |
| DROP TRIGGER trig_row_before_insupd ON rem1;
 | |
| DROP TRIGGER trig_row_after_insupd ON rem1;
 | |
| DROP TRIGGER trig_row_before_delete ON rem1;
 | |
| DROP TRIGGER trig_row_after_delete ON rem1;
 | |
| -- Test various RETURN statements in BEFORE triggers.
 | |
| CREATE FUNCTION trig_row_before_insupdate() RETURNS TRIGGER AS $$
 | |
|   BEGIN
 | |
|     NEW.f2 := NEW.f2 || ' triggered !';
 | |
|     RETURN NEW;
 | |
|   END
 | |
| $$ language plpgsql;
 | |
| CREATE TRIGGER trig_row_before_insupd
 | |
| BEFORE INSERT OR UPDATE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
 | |
| -- The new values should have 'triggered' appended
 | |
| INSERT INTO rem1 values(1, 'insert');
 | |
| SELECT * from loc1;
 | |
|  f1 |         f2         
 | |
| ----+--------------------
 | |
|   1 | insert triggered !
 | |
| (1 row)
 | |
| 
 | |
| INSERT INTO rem1 values(2, 'insert') RETURNING f2;
 | |
|          f2         
 | |
| --------------------
 | |
|  insert triggered !
 | |
| (1 row)
 | |
| 
 | |
| SELECT * from loc1;
 | |
|  f1 |         f2         
 | |
| ----+--------------------
 | |
|   1 | insert triggered !
 | |
|   2 | insert triggered !
 | |
| (2 rows)
 | |
| 
 | |
| UPDATE rem1 set f2 = '';
 | |
| SELECT * from loc1;
 | |
|  f1 |      f2      
 | |
| ----+--------------
 | |
|   1 |  triggered !
 | |
|   2 |  triggered !
 | |
| (2 rows)
 | |
| 
 | |
| UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
 | |
|          f2         
 | |
| --------------------
 | |
|  skidoo triggered !
 | |
|  skidoo triggered !
 | |
| (2 rows)
 | |
| 
 | |
| SELECT * from loc1;
 | |
|  f1 |         f2         
 | |
| ----+--------------------
 | |
|   1 | skidoo triggered !
 | |
|   2 | skidoo triggered !
 | |
| (2 rows)
 | |
| 
 | |
| DELETE FROM rem1;
 | |
| -- Add a second trigger, to check that the changes are propagated correctly
 | |
| -- from trigger to trigger
 | |
| CREATE TRIGGER trig_row_before_insupd2
 | |
| BEFORE INSERT OR UPDATE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
 | |
| INSERT INTO rem1 values(1, 'insert');
 | |
| SELECT * from loc1;
 | |
|  f1 |               f2               
 | |
| ----+--------------------------------
 | |
|   1 | insert triggered ! triggered !
 | |
| (1 row)
 | |
| 
 | |
| INSERT INTO rem1 values(2, 'insert') RETURNING f2;
 | |
|                f2               
 | |
| --------------------------------
 | |
|  insert triggered ! triggered !
 | |
| (1 row)
 | |
| 
 | |
| SELECT * from loc1;
 | |
|  f1 |               f2               
 | |
| ----+--------------------------------
 | |
|   1 | insert triggered ! triggered !
 | |
|   2 | insert triggered ! triggered !
 | |
| (2 rows)
 | |
| 
 | |
| UPDATE rem1 set f2 = '';
 | |
| SELECT * from loc1;
 | |
|  f1 |            f2            
 | |
| ----+--------------------------
 | |
|   1 |  triggered ! triggered !
 | |
|   2 |  triggered ! triggered !
 | |
| (2 rows)
 | |
| 
 | |
| UPDATE rem1 set f2 = 'skidoo' RETURNING f2;
 | |
|                f2               
 | |
| --------------------------------
 | |
|  skidoo triggered ! triggered !
 | |
|  skidoo triggered ! triggered !
 | |
| (2 rows)
 | |
| 
 | |
| SELECT * from loc1;
 | |
|  f1 |               f2               
 | |
| ----+--------------------------------
 | |
|   1 | skidoo triggered ! triggered !
 | |
|   2 | skidoo triggered ! triggered !
 | |
| (2 rows)
 | |
| 
 | |
| DROP TRIGGER trig_row_before_insupd ON rem1;
 | |
| DROP TRIGGER trig_row_before_insupd2 ON rem1;
 | |
| DELETE from rem1;
 | |
| INSERT INTO rem1 VALUES (1, 'test');
 | |
| -- Test with a trigger returning NULL
 | |
| CREATE FUNCTION trig_null() RETURNS TRIGGER AS $$
 | |
|   BEGIN
 | |
|     RETURN NULL;
 | |
|   END
 | |
| $$ language plpgsql;
 | |
| CREATE TRIGGER trig_null
 | |
| BEFORE INSERT OR UPDATE OR DELETE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trig_null();
 | |
| -- Nothing should have changed.
 | |
| INSERT INTO rem1 VALUES (2, 'test2');
 | |
| SELECT * from loc1;
 | |
|  f1 |  f2  
 | |
| ----+------
 | |
|   1 | test
 | |
| (1 row)
 | |
| 
 | |
| UPDATE rem1 SET f2 = 'test2';
 | |
| SELECT * from loc1;
 | |
|  f1 |  f2  
 | |
| ----+------
 | |
|   1 | test
 | |
| (1 row)
 | |
| 
 | |
| DELETE from rem1;
 | |
| SELECT * from loc1;
 | |
|  f1 |  f2  
 | |
| ----+------
 | |
|   1 | test
 | |
| (1 row)
 | |
| 
 | |
| DROP TRIGGER trig_null ON rem1;
 | |
| DELETE from rem1;
 | |
| -- Test a combination of local and remote triggers
 | |
| CREATE TRIGGER trig_row_before
 | |
| BEFORE INSERT OR UPDATE OR DELETE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| CREATE TRIGGER trig_row_after
 | |
| AFTER INSERT OR UPDATE OR DELETE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| CREATE TRIGGER trig_local_before BEFORE INSERT OR UPDATE ON loc1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trig_row_before_insupdate();
 | |
| INSERT INTO rem1(f2) VALUES ('test');
 | |
| NOTICE:  trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
 | |
| NOTICE:  NEW: (12,test)
 | |
| NOTICE:  trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
 | |
| NOTICE:  NEW: (12,"test triggered !")
 | |
| UPDATE rem1 SET f2 = 'testo';
 | |
| NOTICE:  trig_row_before(23, skidoo) BEFORE ROW UPDATE ON rem1
 | |
| NOTICE:  OLD: (12,"test triggered !"),NEW: (12,testo)
 | |
| NOTICE:  trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
 | |
| NOTICE:  OLD: (12,"test triggered !"),NEW: (12,"testo triggered !")
 | |
| -- Test returning a system attribute
 | |
| INSERT INTO rem1(f2) VALUES ('test') RETURNING ctid;
 | |
| NOTICE:  trig_row_before(23, skidoo) BEFORE ROW INSERT ON rem1
 | |
| NOTICE:  NEW: (13,test)
 | |
| NOTICE:  trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
 | |
| NOTICE:  NEW: (13,"test triggered !")
 | |
|   ctid  
 | |
| --------
 | |
|  (0,27)
 | |
| (1 row)
 | |
| 
 | |
| -- cleanup
 | |
| DROP TRIGGER trig_row_before ON rem1;
 | |
| DROP TRIGGER trig_row_after ON rem1;
 | |
| DROP TRIGGER trig_local_before ON loc1;
 | |
| -- Test direct foreign table modification functionality
 | |
| -- Test with statement-level triggers
 | |
| CREATE TRIGGER trig_stmt_before
 | |
| 	BEFORE DELETE OR INSERT OR UPDATE ON rem1
 | |
| 	FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE rem1 set f2 = '';          -- can be pushed down
 | |
|                         QUERY PLAN                        
 | |
| ----------------------------------------------------------
 | |
|  Update on public.rem1
 | |
|    ->  Foreign Update on public.rem1
 | |
|          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| DELETE FROM rem1;                 -- can be pushed down
 | |
|                  QUERY PLAN                  
 | |
| ---------------------------------------------
 | |
|  Delete on public.rem1
 | |
|    ->  Foreign Delete on public.rem1
 | |
|          Remote SQL: DELETE FROM public.loc1
 | |
| (3 rows)
 | |
| 
 | |
| DROP TRIGGER trig_stmt_before ON rem1;
 | |
| CREATE TRIGGER trig_stmt_after
 | |
| 	AFTER DELETE OR INSERT OR UPDATE ON rem1
 | |
| 	FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE rem1 set f2 = '';          -- can be pushed down
 | |
|                         QUERY PLAN                        
 | |
| ----------------------------------------------------------
 | |
|  Update on public.rem1
 | |
|    ->  Foreign Update on public.rem1
 | |
|          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| DELETE FROM rem1;                 -- can be pushed down
 | |
|                  QUERY PLAN                  
 | |
| ---------------------------------------------
 | |
|  Delete on public.rem1
 | |
|    ->  Foreign Delete on public.rem1
 | |
|          Remote SQL: DELETE FROM public.loc1
 | |
| (3 rows)
 | |
| 
 | |
| DROP TRIGGER trig_stmt_after ON rem1;
 | |
| -- Test with row-level ON INSERT triggers
 | |
| CREATE TRIGGER trig_row_before_insert
 | |
| BEFORE INSERT ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE rem1 set f2 = '';          -- can be pushed down
 | |
|                         QUERY PLAN                        
 | |
| ----------------------------------------------------------
 | |
|  Update on public.rem1
 | |
|    ->  Foreign Update on public.rem1
 | |
|          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| DELETE FROM rem1;                 -- can be pushed down
 | |
|                  QUERY PLAN                  
 | |
| ---------------------------------------------
 | |
|  Delete on public.rem1
 | |
|    ->  Foreign Delete on public.rem1
 | |
|          Remote SQL: DELETE FROM public.loc1
 | |
| (3 rows)
 | |
| 
 | |
| DROP TRIGGER trig_row_before_insert ON rem1;
 | |
| CREATE TRIGGER trig_row_after_insert
 | |
| AFTER INSERT ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE rem1 set f2 = '';          -- can be pushed down
 | |
|                         QUERY PLAN                        
 | |
| ----------------------------------------------------------
 | |
|  Update on public.rem1
 | |
|    ->  Foreign Update on public.rem1
 | |
|          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| DELETE FROM rem1;                 -- can be pushed down
 | |
|                  QUERY PLAN                  
 | |
| ---------------------------------------------
 | |
|  Delete on public.rem1
 | |
|    ->  Foreign Delete on public.rem1
 | |
|          Remote SQL: DELETE FROM public.loc1
 | |
| (3 rows)
 | |
| 
 | |
| DROP TRIGGER trig_row_after_insert ON rem1;
 | |
| -- Test with row-level ON UPDATE triggers
 | |
| CREATE TRIGGER trig_row_before_update
 | |
| BEFORE UPDATE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE rem1 set f2 = '';          -- can't be pushed down
 | |
|                              QUERY PLAN                              
 | |
| ---------------------------------------------------------------------
 | |
|  Update on public.rem1
 | |
|    Remote SQL: UPDATE public.loc1 SET f2 = $2 WHERE ctid = $1
 | |
|    ->  Foreign Scan on public.rem1
 | |
|          Output: f1, ''::text, ctid, rem1.*
 | |
|          Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
 | |
| (5 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| DELETE FROM rem1;                 -- can be pushed down
 | |
|                  QUERY PLAN                  
 | |
| ---------------------------------------------
 | |
|  Delete on public.rem1
 | |
|    ->  Foreign Delete on public.rem1
 | |
|          Remote SQL: DELETE FROM public.loc1
 | |
| (3 rows)
 | |
| 
 | |
| DROP TRIGGER trig_row_before_update ON rem1;
 | |
| CREATE TRIGGER trig_row_after_update
 | |
| AFTER UPDATE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE rem1 set f2 = '';          -- can't be pushed down
 | |
|                                   QUERY PLAN                                   
 | |
| -------------------------------------------------------------------------------
 | |
|  Update on public.rem1
 | |
|    Remote SQL: UPDATE public.loc1 SET f2 = $2 WHERE ctid = $1 RETURNING f1, f2
 | |
|    ->  Foreign Scan on public.rem1
 | |
|          Output: f1, ''::text, ctid, rem1.*
 | |
|          Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
 | |
| (5 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| DELETE FROM rem1;                 -- can be pushed down
 | |
|                  QUERY PLAN                  
 | |
| ---------------------------------------------
 | |
|  Delete on public.rem1
 | |
|    ->  Foreign Delete on public.rem1
 | |
|          Remote SQL: DELETE FROM public.loc1
 | |
| (3 rows)
 | |
| 
 | |
| DROP TRIGGER trig_row_after_update ON rem1;
 | |
| -- Test with row-level ON DELETE triggers
 | |
| CREATE TRIGGER trig_row_before_delete
 | |
| BEFORE DELETE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE rem1 set f2 = '';          -- can be pushed down
 | |
|                         QUERY PLAN                        
 | |
| ----------------------------------------------------------
 | |
|  Update on public.rem1
 | |
|    ->  Foreign Update on public.rem1
 | |
|          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| DELETE FROM rem1;                 -- can't be pushed down
 | |
|                              QUERY PLAN                              
 | |
| ---------------------------------------------------------------------
 | |
|  Delete on public.rem1
 | |
|    Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1
 | |
|    ->  Foreign Scan on public.rem1
 | |
|          Output: ctid, rem1.*
 | |
|          Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
 | |
| (5 rows)
 | |
| 
 | |
| DROP TRIGGER trig_row_before_delete ON rem1;
 | |
| CREATE TRIGGER trig_row_after_delete
 | |
| AFTER DELETE ON rem1
 | |
| FOR EACH ROW EXECUTE PROCEDURE trigger_data(23,'skidoo');
 | |
| EXPLAIN (verbose, costs off)
 | |
| UPDATE rem1 set f2 = '';          -- can be pushed down
 | |
|                         QUERY PLAN                        
 | |
| ----------------------------------------------------------
 | |
|  Update on public.rem1
 | |
|    ->  Foreign Update on public.rem1
 | |
|          Remote SQL: UPDATE public.loc1 SET f2 = ''::text
 | |
| (3 rows)
 | |
| 
 | |
| EXPLAIN (verbose, costs off)
 | |
| DELETE FROM rem1;                 -- can't be pushed down
 | |
|                                QUERY PLAN                               
 | |
| ------------------------------------------------------------------------
 | |
|  Delete on public.rem1
 | |
|    Remote SQL: DELETE FROM public.loc1 WHERE ctid = $1 RETURNING f1, f2
 | |
|    ->  Foreign Scan on public.rem1
 | |
|          Output: ctid, rem1.*
 | |
|          Remote SQL: SELECT f1, f2, ctid FROM public.loc1 FOR UPDATE
 | |
| (5 rows)
 | |
| 
 | |
| DROP TRIGGER trig_row_after_delete ON rem1;
 | |
| -- ===================================================================
 | |
| -- test inheritance features
 | |
| -- ===================================================================
 | |
| CREATE TABLE a (aa TEXT);
 | |
| CREATE TABLE loct (aa TEXT, bb TEXT);
 | |
| CREATE FOREIGN TABLE b (bb TEXT) INHERITS (a)
 | |
|   SERVER loopback OPTIONS (table_name 'loct');
 | |
| INSERT INTO a(aa) VALUES('aaa');
 | |
| INSERT INTO a(aa) VALUES('aaaa');
 | |
| INSERT INTO a(aa) VALUES('aaaaa');
 | |
| INSERT INTO b(aa) VALUES('bbb');
 | |
| INSERT INTO b(aa) VALUES('bbbb');
 | |
| INSERT INTO b(aa) VALUES('bbbbb');
 | |
| SELECT tableoid::regclass, * FROM a;
 | |
|  tableoid |  aa   
 | |
| ----------+-------
 | |
|  a        | aaa
 | |
|  a        | aaaa
 | |
|  a        | aaaaa
 | |
|  b        | bbb
 | |
|  b        | bbbb
 | |
|  b        | bbbbb
 | |
| (6 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM b;
 | |
|  tableoid |  aa   | bb 
 | |
| ----------+-------+----
 | |
|  b        | bbb   | 
 | |
|  b        | bbbb  | 
 | |
|  b        | bbbbb | 
 | |
| (3 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM ONLY a;
 | |
|  tableoid |  aa   
 | |
| ----------+-------
 | |
|  a        | aaa
 | |
|  a        | aaaa
 | |
|  a        | aaaaa
 | |
| (3 rows)
 | |
| 
 | |
| UPDATE a SET aa = 'zzzzzz' WHERE aa LIKE 'aaaa%';
 | |
| SELECT tableoid::regclass, * FROM a;
 | |
|  tableoid |   aa   
 | |
| ----------+--------
 | |
|  a        | aaa
 | |
|  a        | zzzzzz
 | |
|  a        | zzzzzz
 | |
|  b        | bbb
 | |
|  b        | bbbb
 | |
|  b        | bbbbb
 | |
| (6 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM b;
 | |
|  tableoid |  aa   | bb 
 | |
| ----------+-------+----
 | |
|  b        | bbb   | 
 | |
|  b        | bbbb  | 
 | |
|  b        | bbbbb | 
 | |
| (3 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM ONLY a;
 | |
|  tableoid |   aa   
 | |
| ----------+--------
 | |
|  a        | aaa
 | |
|  a        | zzzzzz
 | |
|  a        | zzzzzz
 | |
| (3 rows)
 | |
| 
 | |
| UPDATE b SET aa = 'new';
 | |
| SELECT tableoid::regclass, * FROM a;
 | |
|  tableoid |   aa   
 | |
| ----------+--------
 | |
|  a        | aaa
 | |
|  a        | zzzzzz
 | |
|  a        | zzzzzz
 | |
|  b        | new
 | |
|  b        | new
 | |
|  b        | new
 | |
| (6 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM b;
 | |
|  tableoid | aa  | bb 
 | |
| ----------+-----+----
 | |
|  b        | new | 
 | |
|  b        | new | 
 | |
|  b        | new | 
 | |
| (3 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM ONLY a;
 | |
|  tableoid |   aa   
 | |
| ----------+--------
 | |
|  a        | aaa
 | |
|  a        | zzzzzz
 | |
|  a        | zzzzzz
 | |
| (3 rows)
 | |
| 
 | |
| UPDATE a SET aa = 'newtoo';
 | |
| SELECT tableoid::regclass, * FROM a;
 | |
|  tableoid |   aa   
 | |
| ----------+--------
 | |
|  a        | newtoo
 | |
|  a        | newtoo
 | |
|  a        | newtoo
 | |
|  b        | newtoo
 | |
|  b        | newtoo
 | |
|  b        | newtoo
 | |
| (6 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM b;
 | |
|  tableoid |   aa   | bb 
 | |
| ----------+--------+----
 | |
|  b        | newtoo | 
 | |
|  b        | newtoo | 
 | |
|  b        | newtoo | 
 | |
| (3 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM ONLY a;
 | |
|  tableoid |   aa   
 | |
| ----------+--------
 | |
|  a        | newtoo
 | |
|  a        | newtoo
 | |
|  a        | newtoo
 | |
| (3 rows)
 | |
| 
 | |
| DELETE FROM a;
 | |
| SELECT tableoid::regclass, * FROM a;
 | |
|  tableoid | aa 
 | |
| ----------+----
 | |
| (0 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM b;
 | |
|  tableoid | aa | bb 
 | |
| ----------+----+----
 | |
| (0 rows)
 | |
| 
 | |
| SELECT tableoid::regclass, * FROM ONLY a;
 | |
|  tableoid | aa 
 | |
| ----------+----
 | |
| (0 rows)
 | |
| 
 | |
| DROP TABLE a CASCADE;
 | |
| NOTICE:  drop cascades to foreign table b
 | |
| DROP TABLE loct;
 | |
| -- Check SELECT FOR UPDATE/SHARE with an inherited source table
 | |
| create table loct1 (f1 int, f2 int, f3 int);
 | |
| create table loct2 (f1 int, f2 int, f3 int);
 | |
| create table foo (f1 int, f2 int);
 | |
| create foreign table foo2 (f3 int) inherits (foo)
 | |
|   server loopback options (table_name 'loct1');
 | |
| create table bar (f1 int, f2 int);
 | |
| create foreign table bar2 (f3 int) inherits (bar)
 | |
|   server loopback options (table_name 'loct2');
 | |
| insert into foo values(1,1);
 | |
| insert into foo values(3,3);
 | |
| insert into foo2 values(2,2,2);
 | |
| insert into foo2 values(4,4,4);
 | |
| insert into bar values(1,11);
 | |
| insert into bar values(2,22);
 | |
| insert into bar values(6,66);
 | |
| insert into bar2 values(3,33,33);
 | |
| insert into bar2 values(4,44,44);
 | |
| insert into bar2 values(7,77,77);
 | |
| explain (verbose, costs off)
 | |
| select * from bar where f1 in (select f1 from foo) for update;
 | |
|                                           QUERY PLAN                                          
 | |
| ----------------------------------------------------------------------------------------------
 | |
|  LockRows
 | |
|    Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
 | |
|    ->  Hash Join
 | |
|          Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
 | |
|          Hash Cond: (bar.f1 = foo.f1)
 | |
|          ->  Append
 | |
|                ->  Seq Scan on public.bar
 | |
|                      Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid
 | |
|                ->  Foreign Scan on public.bar2
 | |
|                      Output: bar2.f1, bar2.f2, bar2.ctid, bar2.*, bar2.tableoid
 | |
|                      Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
 | |
|          ->  Hash
 | |
|                Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                ->  HashAggregate
 | |
|                      Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                      Group Key: foo.f1
 | |
|                      ->  Append
 | |
|                            ->  Seq Scan on public.foo
 | |
|                                  Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                            ->  Foreign Scan on public.foo2
 | |
|                                  Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
 | |
|                                  Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
 | |
| (22 rows)
 | |
| 
 | |
| select * from bar where f1 in (select f1 from foo) for update;
 | |
|  f1 | f2 
 | |
| ----+----
 | |
|   1 | 11
 | |
|   2 | 22
 | |
|   3 | 33
 | |
|   4 | 44
 | |
| (4 rows)
 | |
| 
 | |
| explain (verbose, costs off)
 | |
| select * from bar where f1 in (select f1 from foo) for share;
 | |
|                                           QUERY PLAN                                          
 | |
| ----------------------------------------------------------------------------------------------
 | |
|  LockRows
 | |
|    Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
 | |
|    ->  Hash Join
 | |
|          Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid, foo.ctid, foo.*, foo.tableoid
 | |
|          Hash Cond: (bar.f1 = foo.f1)
 | |
|          ->  Append
 | |
|                ->  Seq Scan on public.bar
 | |
|                      Output: bar.f1, bar.f2, bar.ctid, bar.*, bar.tableoid
 | |
|                ->  Foreign Scan on public.bar2
 | |
|                      Output: bar2.f1, bar2.f2, bar2.ctid, bar2.*, bar2.tableoid
 | |
|                      Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR SHARE
 | |
|          ->  Hash
 | |
|                Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                ->  HashAggregate
 | |
|                      Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                      Group Key: foo.f1
 | |
|                      ->  Append
 | |
|                            ->  Seq Scan on public.foo
 | |
|                                  Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                            ->  Foreign Scan on public.foo2
 | |
|                                  Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
 | |
|                                  Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
 | |
| (22 rows)
 | |
| 
 | |
| select * from bar where f1 in (select f1 from foo) for share;
 | |
|  f1 | f2 
 | |
| ----+----
 | |
|   1 | 11
 | |
|   2 | 22
 | |
|   3 | 33
 | |
|   4 | 44
 | |
| (4 rows)
 | |
| 
 | |
| -- Check UPDATE with inherited target and an inherited source table
 | |
| explain (verbose, costs off)
 | |
| update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
 | |
|                                          QUERY PLAN                                          
 | |
| ---------------------------------------------------------------------------------------------
 | |
|  Update on public.bar
 | |
|    Update on public.bar
 | |
|    Foreign Update on public.bar2
 | |
|      Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
 | |
|    ->  Hash Join
 | |
|          Output: bar.f1, (bar.f2 + 100), bar.ctid, foo.ctid, foo.*, foo.tableoid
 | |
|          Hash Cond: (bar.f1 = foo.f1)
 | |
|          ->  Seq Scan on public.bar
 | |
|                Output: bar.f1, bar.f2, bar.ctid
 | |
|          ->  Hash
 | |
|                Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                ->  HashAggregate
 | |
|                      Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                      Group Key: foo.f1
 | |
|                      ->  Append
 | |
|                            ->  Seq Scan on public.foo
 | |
|                                  Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                            ->  Foreign Scan on public.foo2
 | |
|                                  Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
 | |
|                                  Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
 | |
|    ->  Hash Join
 | |
|          Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.ctid, foo.ctid, foo.*, foo.tableoid
 | |
|          Hash Cond: (bar2.f1 = foo.f1)
 | |
|          ->  Foreign Scan on public.bar2
 | |
|                Output: bar2.f1, bar2.f2, bar2.f3, bar2.ctid
 | |
|                Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
 | |
|          ->  Hash
 | |
|                Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                ->  HashAggregate
 | |
|                      Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                      Group Key: foo.f1
 | |
|                      ->  Append
 | |
|                            ->  Seq Scan on public.foo
 | |
|                                  Output: foo.ctid, foo.*, foo.tableoid, foo.f1
 | |
|                            ->  Foreign Scan on public.foo2
 | |
|                                  Output: foo2.ctid, foo2.*, foo2.tableoid, foo2.f1
 | |
|                                  Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct1
 | |
| (37 rows)
 | |
| 
 | |
| update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
 | |
| select tableoid::regclass, * from bar order by 1,2;
 | |
|  tableoid | f1 | f2  
 | |
| ----------+----+-----
 | |
|  bar      |  1 | 111
 | |
|  bar      |  2 | 122
 | |
|  bar      |  6 |  66
 | |
|  bar2     |  3 | 133
 | |
|  bar2     |  4 | 144
 | |
|  bar2     |  7 |  77
 | |
| (6 rows)
 | |
| 
 | |
| -- Check UPDATE with inherited target and an appendrel subquery
 | |
| explain (verbose, costs off)
 | |
| update bar set f2 = f2 + 100
 | |
| from
 | |
|   ( select f1 from foo union all select f1+3 from foo ) ss
 | |
| where bar.f1 = ss.f1;
 | |
|                                       QUERY PLAN                                      
 | |
| --------------------------------------------------------------------------------------
 | |
|  Update on public.bar
 | |
|    Update on public.bar
 | |
|    Foreign Update on public.bar2
 | |
|      Remote SQL: UPDATE public.loct2 SET f2 = $2 WHERE ctid = $1
 | |
|    ->  Hash Join
 | |
|          Output: bar.f1, (bar.f2 + 100), bar.ctid, (ROW(foo.f1))
 | |
|          Hash Cond: (foo.f1 = bar.f1)
 | |
|          ->  Append
 | |
|                ->  Seq Scan on public.foo
 | |
|                      Output: ROW(foo.f1), foo.f1
 | |
|                ->  Foreign Scan on public.foo2
 | |
|                      Output: ROW(foo2.f1), foo2.f1
 | |
|                      Remote SQL: SELECT f1 FROM public.loct1
 | |
|                ->  Seq Scan on public.foo foo_1
 | |
|                      Output: ROW((foo_1.f1 + 3)), (foo_1.f1 + 3)
 | |
|                ->  Foreign Scan on public.foo2 foo2_1
 | |
|                      Output: ROW((foo2_1.f1 + 3)), (foo2_1.f1 + 3)
 | |
|                      Remote SQL: SELECT f1 FROM public.loct1
 | |
|          ->  Hash
 | |
|                Output: bar.f1, bar.f2, bar.ctid
 | |
|                ->  Seq Scan on public.bar
 | |
|                      Output: bar.f1, bar.f2, bar.ctid
 | |
|    ->  Merge Join
 | |
|          Output: bar2.f1, (bar2.f2 + 100), bar2.f3, bar2.ctid, (ROW(foo.f1))
 | |
|          Merge Cond: (bar2.f1 = foo.f1)
 | |
|          ->  Sort
 | |
|                Output: bar2.f1, bar2.f2, bar2.f3, bar2.ctid
 | |
|                Sort Key: bar2.f1
 | |
|                ->  Foreign Scan on public.bar2
 | |
|                      Output: bar2.f1, bar2.f2, bar2.f3, bar2.ctid
 | |
|                      Remote SQL: SELECT f1, f2, f3, ctid FROM public.loct2 FOR UPDATE
 | |
|          ->  Sort
 | |
|                Output: (ROW(foo.f1)), foo.f1
 | |
|                Sort Key: foo.f1
 | |
|                ->  Append
 | |
|                      ->  Seq Scan on public.foo
 | |
|                            Output: ROW(foo.f1), foo.f1
 | |
|                      ->  Foreign Scan on public.foo2
 | |
|                            Output: ROW(foo2.f1), foo2.f1
 | |
|                            Remote SQL: SELECT f1 FROM public.loct1
 | |
|                      ->  Seq Scan on public.foo foo_1
 | |
|                            Output: ROW((foo_1.f1 + 3)), (foo_1.f1 + 3)
 | |
|                      ->  Foreign Scan on public.foo2 foo2_1
 | |
|                            Output: ROW((foo2_1.f1 + 3)), (foo2_1.f1 + 3)
 | |
|                            Remote SQL: SELECT f1 FROM public.loct1
 | |
| (45 rows)
 | |
| 
 | |
| update bar set f2 = f2 + 100
 | |
| from
 | |
|   ( select f1 from foo union all select f1+3 from foo ) ss
 | |
| where bar.f1 = ss.f1;
 | |
| select tableoid::regclass, * from bar order by 1,2;
 | |
|  tableoid | f1 | f2  
 | |
| ----------+----+-----
 | |
|  bar      |  1 | 211
 | |
|  bar      |  2 | 222
 | |
|  bar      |  6 | 166
 | |
|  bar2     |  3 | 233
 | |
|  bar2     |  4 | 244
 | |
|  bar2     |  7 | 177
 | |
| (6 rows)
 | |
| 
 | |
| -- Test forcing the remote server to produce sorted data for a merge join,
 | |
| -- but the foreign table is an inheritance child.
 | |
| truncate table loct1;
 | |
| truncate table only foo;
 | |
| \set num_rows_foo 2000
 | |
| 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);
 | |
| insert into foo select generate_series(1, :num_rows_foo, 2), generate_series(1, :num_rows_foo, 2);
 | |
| SET enable_hashjoin to false;
 | |
| SET enable_nestloop to false;
 | |
| alter foreign table foo2 options (use_remote_estimate 'true');
 | |
| create index i_loct1_f1 on loct1(f1);
 | |
| create index i_foo_f1 on foo(f1);
 | |
| analyze foo;
 | |
| analyze loct1;
 | |
| -- inner join; expressions in the clauses appear in the equivalence class list
 | |
| explain (verbose, costs off)
 | |
| 	select foo.f1, loct1.f1 from foo join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
 | |
|                                             QUERY PLAN                                            
 | |
| --------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: foo.f1, loct1.f1, foo.f2
 | |
|    ->  Sort
 | |
|          Output: foo.f1, loct1.f1, foo.f2
 | |
|          Sort Key: foo.f2
 | |
|          ->  Merge Join
 | |
|                Output: foo.f1, loct1.f1, foo.f2
 | |
|                Merge Cond: (foo.f1 = loct1.f1)
 | |
|                ->  Merge Append
 | |
|                      Sort Key: foo.f1
 | |
|                      ->  Index Scan using i_foo_f1 on public.foo
 | |
|                            Output: foo.f1, foo.f2
 | |
|                      ->  Foreign Scan on public.foo2
 | |
|                            Output: foo2.f1, foo2.f2
 | |
|                            Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
 | |
|                ->  Index Only Scan using i_loct1_f1 on public.loct1
 | |
|                      Output: loct1.f1
 | |
| (17 rows)
 | |
| 
 | |
| select foo.f1, loct1.f1 from foo join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
 | |
|  f1 | f1 
 | |
| ----+----
 | |
|  20 | 20
 | |
|  22 | 22
 | |
|  24 | 24
 | |
|  26 | 26
 | |
|  28 | 28
 | |
|  30 | 30
 | |
|  32 | 32
 | |
|  34 | 34
 | |
|  36 | 36
 | |
|  38 | 38
 | |
| (10 rows)
 | |
| 
 | |
| -- outer join; expressions in the clauses do not appear in equivalence class
 | |
| -- list but no output change as compared to the previous query
 | |
| explain (verbose, costs off)
 | |
| 	select foo.f1, loct1.f1 from foo left join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
 | |
|                                             QUERY PLAN                                            
 | |
| --------------------------------------------------------------------------------------------------
 | |
|  Limit
 | |
|    Output: foo.f1, loct1.f1, foo.f2
 | |
|    ->  Sort
 | |
|          Output: foo.f1, loct1.f1, foo.f2
 | |
|          Sort Key: foo.f2
 | |
|          ->  Merge Left Join
 | |
|                Output: foo.f1, loct1.f1, foo.f2
 | |
|                Merge Cond: (foo.f1 = loct1.f1)
 | |
|                ->  Merge Append
 | |
|                      Sort Key: foo.f1
 | |
|                      ->  Index Scan using i_foo_f1 on public.foo
 | |
|                            Output: foo.f1, foo.f2
 | |
|                      ->  Foreign Scan on public.foo2
 | |
|                            Output: foo2.f1, foo2.f2
 | |
|                            Remote SQL: SELECT f1, f2 FROM public.loct1 ORDER BY f1 ASC NULLS LAST
 | |
|                ->  Index Only Scan using i_loct1_f1 on public.loct1
 | |
|                      Output: loct1.f1
 | |
| (17 rows)
 | |
| 
 | |
| select foo.f1, loct1.f1 from foo left join loct1 on (foo.f1 = loct1.f1) order by foo.f2 offset 10 limit 10;
 | |
|  f1 | f1 
 | |
| ----+----
 | |
|  10 | 10
 | |
|  11 |   
 | |
|  12 | 12
 | |
|  13 |   
 | |
|  14 | 14
 | |
|  15 |   
 | |
|  16 | 16
 | |
|  17 |   
 | |
|  18 | 18
 | |
|  19 |   
 | |
| (10 rows)
 | |
| 
 | |
| RESET enable_hashjoin;
 | |
| RESET enable_nestloop;
 | |
| -- Test that WHERE CURRENT OF is not supported
 | |
| begin;
 | |
| declare c cursor for select * from bar where f1 = 7;
 | |
| fetch from c;
 | |
|  f1 | f2  
 | |
| ----+-----
 | |
|   7 | 177
 | |
| (1 row)
 | |
| 
 | |
| update bar set f2 = null where current of c;
 | |
| ERROR:  WHERE CURRENT OF is not supported for this table type
 | |
| rollback;
 | |
| explain (verbose, costs off)
 | |
| delete from foo where f1 < 5 returning *;
 | |
|                                    QUERY PLAN                                   
 | |
| --------------------------------------------------------------------------------
 | |
|  Delete on public.foo
 | |
|    Output: foo.f1, foo.f2
 | |
|    Delete on public.foo
 | |
|    Foreign Delete on public.foo2
 | |
|    ->  Index Scan using i_foo_f1 on public.foo
 | |
|          Output: foo.ctid
 | |
|          Index Cond: (foo.f1 < 5)
 | |
|    ->  Foreign Delete on public.foo2
 | |
|          Remote SQL: DELETE FROM public.loct1 WHERE ((f1 < 5)) RETURNING f1, f2
 | |
| (9 rows)
 | |
| 
 | |
| delete from foo where f1 < 5 returning *;
 | |
|  f1 | f2 
 | |
| ----+----
 | |
|   1 |  1
 | |
|   3 |  3
 | |
|   0 |  0
 | |
|   2 |  2
 | |
|   4 |  4
 | |
| (5 rows)
 | |
| 
 | |
| explain (verbose, costs off)
 | |
| update bar set f2 = f2 + 100 returning *;
 | |
|                                   QUERY PLAN                                  
 | |
| ------------------------------------------------------------------------------
 | |
|  Update on public.bar
 | |
|    Output: bar.f1, bar.f2
 | |
|    Update on public.bar
 | |
|    Foreign Update on public.bar2
 | |
|    ->  Seq Scan on public.bar
 | |
|          Output: bar.f1, (bar.f2 + 100), bar.ctid
 | |
|    ->  Foreign Update on public.bar2
 | |
|          Remote SQL: UPDATE public.loct2 SET f2 = (f2 + 100) RETURNING f1, f2
 | |
| (8 rows)
 | |
| 
 | |
| update bar set f2 = f2 + 100 returning *;
 | |
|  f1 | f2  
 | |
| ----+-----
 | |
|   1 | 311
 | |
|   2 | 322
 | |
|   6 | 266
 | |
|   3 | 333
 | |
|   4 | 344
 | |
|   7 | 277
 | |
| (6 rows)
 | |
| 
 | |
| drop table foo cascade;
 | |
| NOTICE:  drop cascades to foreign table foo2
 | |
| drop table bar cascade;
 | |
| NOTICE:  drop cascades to foreign table bar2
 | |
| drop table loct1;
 | |
| drop table loct2;
 | |
| -- ===================================================================
 | |
| -- test IMPORT FOREIGN SCHEMA
 | |
| -- ===================================================================
 | |
| CREATE SCHEMA import_source;
 | |
| CREATE TABLE import_source.t1 (c1 int, c2 varchar NOT NULL);
 | |
| CREATE TABLE import_source.t2 (c1 int default 42, c2 varchar NULL, c3 text collate "POSIX");
 | |
| CREATE TYPE typ1 AS (m1 int, m2 varchar);
 | |
| CREATE TABLE import_source.t3 (c1 timestamptz default now(), c2 typ1);
 | |
| CREATE TABLE import_source."x 4" (c1 float8, "C 2" text, c3 varchar(42));
 | |
| CREATE TABLE import_source."x 5" (c1 float8);
 | |
| ALTER TABLE import_source."x 5" DROP COLUMN c1;
 | |
| CREATE SCHEMA import_dest1;
 | |
| IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest1;
 | |
| \det+ import_dest1.*
 | |
|                                      List of foreign tables
 | |
|     Schema    | Table |  Server  |                   FDW Options                   | Description 
 | |
| --------------+-------+----------+-------------------------------------------------+-------------
 | |
|  import_dest1 | t1    | loopback | (schema_name 'import_source', table_name 't1')  | 
 | |
|  import_dest1 | t2    | loopback | (schema_name 'import_source', table_name 't2')  | 
 | |
|  import_dest1 | t3    | loopback | (schema_name 'import_source', table_name 't3')  | 
 | |
|  import_dest1 | x 4   | loopback | (schema_name 'import_source', table_name 'x 4') | 
 | |
|  import_dest1 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') | 
 | |
| (5 rows)
 | |
| 
 | |
| \d import_dest1.*
 | |
|                          Foreign table "import_dest1.t1"
 | |
|  Column |       Type        | Collation | Nullable | Default |    FDW Options     
 | |
| --------+-------------------+-----------+----------+---------+--------------------
 | |
|  c1     | integer           |           |          |         | (column_name 'c1')
 | |
|  c2     | character varying |           | not null |         | (column_name 'c2')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 't1')
 | |
| 
 | |
|                          Foreign table "import_dest1.t2"
 | |
|  Column |       Type        | Collation | Nullable | Default |    FDW Options     
 | |
| --------+-------------------+-----------+----------+---------+--------------------
 | |
|  c1     | integer           |           |          |         | (column_name 'c1')
 | |
|  c2     | character varying |           |          |         | (column_name 'c2')
 | |
|  c3     | text              | POSIX     |          |         | (column_name 'c3')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 't2')
 | |
| 
 | |
|                              Foreign table "import_dest1.t3"
 | |
|  Column |           Type           | Collation | Nullable | Default |    FDW Options     
 | |
| --------+--------------------------+-----------+----------+---------+--------------------
 | |
|  c1     | timestamp with time zone |           |          |         | (column_name 'c1')
 | |
|  c2     | typ1                     |           |          |         | (column_name 'c2')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 't3')
 | |
| 
 | |
|                            Foreign table "import_dest1.x 4"
 | |
|  Column |         Type          | Collation | Nullable | Default |     FDW Options     
 | |
| --------+-----------------------+-----------+----------+---------+---------------------
 | |
|  c1     | double precision      |           |          |         | (column_name 'c1')
 | |
|  C 2    | text                  |           |          |         | (column_name 'C 2')
 | |
|  c3     | character varying(42) |           |          |         | (column_name 'c3')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 'x 4')
 | |
| 
 | |
|                Foreign table "import_dest1.x 5"
 | |
|  Column | Type | Collation | Nullable | Default | FDW Options 
 | |
| --------+------+-----------+----------+---------+-------------
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 'x 5')
 | |
| 
 | |
| -- Options
 | |
| CREATE SCHEMA import_dest2;
 | |
| IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest2
 | |
|   OPTIONS (import_default 'true');
 | |
| \det+ import_dest2.*
 | |
|                                      List of foreign tables
 | |
|     Schema    | Table |  Server  |                   FDW Options                   | Description 
 | |
| --------------+-------+----------+-------------------------------------------------+-------------
 | |
|  import_dest2 | t1    | loopback | (schema_name 'import_source', table_name 't1')  | 
 | |
|  import_dest2 | t2    | loopback | (schema_name 'import_source', table_name 't2')  | 
 | |
|  import_dest2 | t3    | loopback | (schema_name 'import_source', table_name 't3')  | 
 | |
|  import_dest2 | x 4   | loopback | (schema_name 'import_source', table_name 'x 4') | 
 | |
|  import_dest2 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') | 
 | |
| (5 rows)
 | |
| 
 | |
| \d import_dest2.*
 | |
|                          Foreign table "import_dest2.t1"
 | |
|  Column |       Type        | Collation | Nullable | Default |    FDW Options     
 | |
| --------+-------------------+-----------+----------+---------+--------------------
 | |
|  c1     | integer           |           |          |         | (column_name 'c1')
 | |
|  c2     | character varying |           | not null |         | (column_name 'c2')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 't1')
 | |
| 
 | |
|                          Foreign table "import_dest2.t2"
 | |
|  Column |       Type        | Collation | Nullable | Default |    FDW Options     
 | |
| --------+-------------------+-----------+----------+---------+--------------------
 | |
|  c1     | integer           |           |          | 42      | (column_name 'c1')
 | |
|  c2     | character varying |           |          |         | (column_name 'c2')
 | |
|  c3     | text              | POSIX     |          |         | (column_name 'c3')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 't2')
 | |
| 
 | |
|                              Foreign table "import_dest2.t3"
 | |
|  Column |           Type           | Collation | Nullable | Default |    FDW Options     
 | |
| --------+--------------------------+-----------+----------+---------+--------------------
 | |
|  c1     | timestamp with time zone |           |          | now()   | (column_name 'c1')
 | |
|  c2     | typ1                     |           |          |         | (column_name 'c2')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 't3')
 | |
| 
 | |
|                            Foreign table "import_dest2.x 4"
 | |
|  Column |         Type          | Collation | Nullable | Default |     FDW Options     
 | |
| --------+-----------------------+-----------+----------+---------+---------------------
 | |
|  c1     | double precision      |           |          |         | (column_name 'c1')
 | |
|  C 2    | text                  |           |          |         | (column_name 'C 2')
 | |
|  c3     | character varying(42) |           |          |         | (column_name 'c3')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 'x 4')
 | |
| 
 | |
|                Foreign table "import_dest2.x 5"
 | |
|  Column | Type | Collation | Nullable | Default | FDW Options 
 | |
| --------+------+-----------+----------+---------+-------------
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 'x 5')
 | |
| 
 | |
| CREATE SCHEMA import_dest3;
 | |
| IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest3
 | |
|   OPTIONS (import_collate 'false', import_not_null 'false');
 | |
| \det+ import_dest3.*
 | |
|                                      List of foreign tables
 | |
|     Schema    | Table |  Server  |                   FDW Options                   | Description 
 | |
| --------------+-------+----------+-------------------------------------------------+-------------
 | |
|  import_dest3 | t1    | loopback | (schema_name 'import_source', table_name 't1')  | 
 | |
|  import_dest3 | t2    | loopback | (schema_name 'import_source', table_name 't2')  | 
 | |
|  import_dest3 | t3    | loopback | (schema_name 'import_source', table_name 't3')  | 
 | |
|  import_dest3 | x 4   | loopback | (schema_name 'import_source', table_name 'x 4') | 
 | |
|  import_dest3 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') | 
 | |
| (5 rows)
 | |
| 
 | |
| \d import_dest3.*
 | |
|                          Foreign table "import_dest3.t1"
 | |
|  Column |       Type        | Collation | Nullable | Default |    FDW Options     
 | |
| --------+-------------------+-----------+----------+---------+--------------------
 | |
|  c1     | integer           |           |          |         | (column_name 'c1')
 | |
|  c2     | character varying |           |          |         | (column_name 'c2')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 't1')
 | |
| 
 | |
|                          Foreign table "import_dest3.t2"
 | |
|  Column |       Type        | Collation | Nullable | Default |    FDW Options     
 | |
| --------+-------------------+-----------+----------+---------+--------------------
 | |
|  c1     | integer           |           |          |         | (column_name 'c1')
 | |
|  c2     | character varying |           |          |         | (column_name 'c2')
 | |
|  c3     | text              |           |          |         | (column_name 'c3')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 't2')
 | |
| 
 | |
|                              Foreign table "import_dest3.t3"
 | |
|  Column |           Type           | Collation | Nullable | Default |    FDW Options     
 | |
| --------+--------------------------+-----------+----------+---------+--------------------
 | |
|  c1     | timestamp with time zone |           |          |         | (column_name 'c1')
 | |
|  c2     | typ1                     |           |          |         | (column_name 'c2')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 't3')
 | |
| 
 | |
|                            Foreign table "import_dest3.x 4"
 | |
|  Column |         Type          | Collation | Nullable | Default |     FDW Options     
 | |
| --------+-----------------------+-----------+----------+---------+---------------------
 | |
|  c1     | double precision      |           |          |         | (column_name 'c1')
 | |
|  C 2    | text                  |           |          |         | (column_name 'C 2')
 | |
|  c3     | character varying(42) |           |          |         | (column_name 'c3')
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 'x 4')
 | |
| 
 | |
|                Foreign table "import_dest3.x 5"
 | |
|  Column | Type | Collation | Nullable | Default | FDW Options 
 | |
| --------+------+-----------+----------+---------+-------------
 | |
| Server: loopback
 | |
| FDW Options: (schema_name 'import_source', table_name 'x 5')
 | |
| 
 | |
| -- Check LIMIT TO and EXCEPT
 | |
| CREATE SCHEMA import_dest4;
 | |
| IMPORT FOREIGN SCHEMA import_source LIMIT TO (t1, nonesuch)
 | |
|   FROM SERVER loopback INTO import_dest4;
 | |
| \det+ import_dest4.*
 | |
|                                      List of foreign tables
 | |
|     Schema    | Table |  Server  |                  FDW Options                   | Description 
 | |
| --------------+-------+----------+------------------------------------------------+-------------
 | |
|  import_dest4 | t1    | loopback | (schema_name 'import_source', table_name 't1') | 
 | |
| (1 row)
 | |
| 
 | |
| IMPORT FOREIGN SCHEMA import_source EXCEPT (t1, "x 4", nonesuch)
 | |
|   FROM SERVER loopback INTO import_dest4;
 | |
| \det+ import_dest4.*
 | |
|                                      List of foreign tables
 | |
|     Schema    | Table |  Server  |                   FDW Options                   | Description 
 | |
| --------------+-------+----------+-------------------------------------------------+-------------
 | |
|  import_dest4 | t1    | loopback | (schema_name 'import_source', table_name 't1')  | 
 | |
|  import_dest4 | t2    | loopback | (schema_name 'import_source', table_name 't2')  | 
 | |
|  import_dest4 | t3    | loopback | (schema_name 'import_source', table_name 't3')  | 
 | |
|  import_dest4 | x 5   | loopback | (schema_name 'import_source', table_name 'x 5') | 
 | |
| (4 rows)
 | |
| 
 | |
| -- Assorted error cases
 | |
| IMPORT FOREIGN SCHEMA import_source FROM SERVER loopback INTO import_dest4;
 | |
| ERROR:  relation "t1" already exists
 | |
| CONTEXT:  importing foreign table "t1"
 | |
| IMPORT FOREIGN SCHEMA nonesuch FROM SERVER loopback INTO import_dest4;
 | |
| ERROR:  schema "nonesuch" is not present on foreign server "loopback"
 | |
| IMPORT FOREIGN SCHEMA nonesuch FROM SERVER loopback INTO notthere;
 | |
| ERROR:  schema "notthere" does not exist
 | |
| IMPORT FOREIGN SCHEMA nonesuch FROM SERVER nowhere INTO notthere;
 | |
| ERROR:  server "nowhere" does not exist
 | |
| -- Check case of a type present only on the remote server.
 | |
| -- We can fake this by dropping the type locally in our transaction.
 | |
| CREATE TYPE "Colors" AS ENUM ('red', 'green', 'blue');
 | |
| CREATE TABLE import_source.t5 (c1 int, c2 text collate "C", "Col" "Colors");
 | |
| CREATE SCHEMA import_dest5;
 | |
| BEGIN;
 | |
| DROP TYPE "Colors" CASCADE;
 | |
| NOTICE:  drop cascades to table import_source.t5 column Col
 | |
| IMPORT FOREIGN SCHEMA import_source LIMIT TO (t5)
 | |
|   FROM SERVER loopback INTO import_dest5;  -- ERROR
 | |
| ERROR:  type "public.Colors" does not exist
 | |
| LINE 4:   "Col" public."Colors" OPTIONS (column_name 'Col')
 | |
|                 ^
 | |
| QUERY:  CREATE FOREIGN TABLE t5 (
 | |
|   c1 integer OPTIONS (column_name 'c1'),
 | |
|   c2 text OPTIONS (column_name 'c2') COLLATE pg_catalog."C",
 | |
|   "Col" public."Colors" OPTIONS (column_name 'Col')
 | |
| ) SERVER loopback
 | |
| OPTIONS (schema_name 'import_source', table_name 't5');
 | |
| CONTEXT:  importing foreign table "t5"
 | |
| ROLLBACK;
 | |
| BEGIN;
 | |
| CREATE SERVER fetch101 FOREIGN DATA WRAPPER postgres_fdw OPTIONS( fetch_size '101' );
 | |
| SELECT count(*)
 | |
| FROM pg_foreign_server
 | |
| WHERE srvname = 'fetch101'
 | |
| AND srvoptions @> array['fetch_size=101'];
 | |
|  count 
 | |
| -------
 | |
|      1
 | |
| (1 row)
 | |
| 
 | |
| ALTER SERVER fetch101 OPTIONS( SET fetch_size '202' );
 | |
| SELECT count(*)
 | |
| FROM pg_foreign_server
 | |
| WHERE srvname = 'fetch101'
 | |
| AND srvoptions @> array['fetch_size=101'];
 | |
|  count 
 | |
| -------
 | |
|      0
 | |
| (1 row)
 | |
| 
 | |
| SELECT count(*)
 | |
| FROM pg_foreign_server
 | |
| WHERE srvname = 'fetch101'
 | |
| AND srvoptions @> array['fetch_size=202'];
 | |
|  count 
 | |
| -------
 | |
|      1
 | |
| (1 row)
 | |
| 
 | |
| CREATE FOREIGN TABLE table30000 ( x int ) SERVER fetch101 OPTIONS ( fetch_size '30000' );
 | |
| SELECT COUNT(*)
 | |
| FROM pg_foreign_table
 | |
| WHERE ftrelid = 'table30000'::regclass
 | |
| AND ftoptions @> array['fetch_size=30000'];
 | |
|  count 
 | |
| -------
 | |
|      1
 | |
| (1 row)
 | |
| 
 | |
| ALTER FOREIGN TABLE table30000 OPTIONS ( SET fetch_size '60000');
 | |
| SELECT COUNT(*)
 | |
| FROM pg_foreign_table
 | |
| WHERE ftrelid = 'table30000'::regclass
 | |
| AND ftoptions @> array['fetch_size=30000'];
 | |
|  count 
 | |
| -------
 | |
|      0
 | |
| (1 row)
 | |
| 
 | |
| SELECT COUNT(*)
 | |
| FROM pg_foreign_table
 | |
| WHERE ftrelid = 'table30000'::regclass
 | |
| AND ftoptions @> array['fetch_size=60000'];
 | |
|  count 
 | |
| -------
 | |
|      1
 | |
| (1 row)
 | |
| 
 | |
| ROLLBACK;
 |