@ -197,23 +197,23 @@ ALTER FOREIGN TABLE ft2 OPTIONS (use_remote_estimate 'true');
-- simple queries
-- simple queries
-- ===================================================================
-- ===================================================================
-- single table without alias
-- single table without alias
EXPLAIN ( COSTS false ) SELECT * FROM ft1 ORDER BY c3 , c1 OFFSET 100 LIMIT 10 ;
EXPLAIN ( COSTS OFF ) SELECT * FROM ft1 ORDER BY c3 , c1 OFFSET 100 LIMIT 10 ;
SELECT * FROM ft1 ORDER BY c3 , c1 OFFSET 100 LIMIT 10 ;
SELECT * FROM ft1 ORDER BY c3 , c1 OFFSET 100 LIMIT 10 ;
-- single table with alias - also test that tableoid sort is not pushed to remote side
-- single table with alias - also test that tableoid sort is not pushed to remote side
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 ORDER BY t1 . c3 , t1 . c1 , t1 . tableoid OFFSET 100 LIMIT 10 ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 ORDER BY t1 . c3 , t1 . c1 , t1 . tableoid OFFSET 100 LIMIT 10 ;
SELECT * FROM ft1 t1 ORDER BY t1 . c3 , t1 . c1 , t1 . tableoid OFFSET 100 LIMIT 10 ;
SELECT * FROM ft1 t1 ORDER BY t1 . c3 , t1 . c1 , t1 . tableoid OFFSET 100 LIMIT 10 ;
-- whole-row reference
-- whole-row reference
EXPLAIN ( VERBOSE , COSTS false ) SELECT t1 FROM ft1 t1 ORDER BY t1 . c3 , t1 . c1 OFFSET 100 LIMIT 10 ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT t1 FROM ft1 t1 ORDER BY t1 . c3 , t1 . c1 OFFSET 100 LIMIT 10 ;
SELECT t1 FROM ft1 t1 ORDER BY t1 . c3 , t1 . c1 OFFSET 100 LIMIT 10 ;
SELECT t1 FROM ft1 t1 ORDER BY t1 . c3 , t1 . c1 OFFSET 100 LIMIT 10 ;
-- empty result
-- empty result
SELECT * FROM ft1 WHERE false ;
SELECT * FROM ft1 WHERE false ;
-- with WHERE clause
-- with WHERE clause
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE t1 . c1 = 101 AND t1 . c6 = ' 1 ' AND t1 . c7 > = ' 1 ' ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE t1 . c1 = 101 AND t1 . c6 = ' 1 ' AND t1 . c7 > = ' 1 ' ;
SELECT * FROM ft1 t1 WHERE t1 . c1 = 101 AND t1 . c6 = ' 1 ' AND t1 . c7 > = ' 1 ' ;
SELECT * FROM ft1 t1 WHERE t1 . c1 = 101 AND t1 . c6 = ' 1 ' AND t1 . c7 > = ' 1 ' ;
-- with FOR UPDATE/SHARE
-- with FOR UPDATE/SHARE
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE ;
SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE ;
SELECT * FROM ft1 t1 WHERE c1 = 101 FOR UPDATE ;
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE ;
SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE ;
SELECT * FROM ft1 t1 WHERE c1 = 102 FOR SHARE ;
-- aggregate
-- aggregate
SELECT COUNT ( * ) FROM ft1 t1 ;
SELECT COUNT ( * ) FROM ft1 t1 ;
@ -229,27 +229,27 @@ SELECT 'fixed', NULL FROM ft1 t1 WHERE c1 = 1;
SET enable_hashjoin TO false ;
SET enable_hashjoin TO false ;
SET enable_nestloop TO false ;
SET enable_nestloop TO false ;
-- inner join; expressions in the clauses appear in the equivalence class list
-- inner join; expressions in the clauses appear in the equivalence class list
EXPLAIN ( VERBOSE , COSTS false )
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 ;
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 ;
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 ;
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 ;
-- outer join; expressions in the clauses do not appear in equivalence class
-- outer join; expressions in the clauses do not appear in equivalence class
-- list but no output change as compared to the previous query
-- list but no output change as compared to the previous query
EXPLAIN ( VERBOSE , COSTS false )
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 ;
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 ;
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 ;
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 ;
-- A join between local table and foreign join. ORDER BY clause is added to the
-- 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.
-- foreign join so that the local table can be joined using merge join strategy.
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- Test similar to above, except that the full join prevents any equivalence
-- Test similar to above, except that the full join prevents any equivalence
-- classes from being merged. This produces single relation equivalence classes
-- classes from being merged. This produces single relation equivalence classes
-- included in join restrictions.
-- included in join restrictions.
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- Test similar to above with all full outer joins
-- Test similar to above with all full outer joins
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
RESET enable_hashjoin ;
RESET enable_hashjoin ;
@ -258,25 +258,25 @@ RESET enable_nestloop;
-- ===================================================================
-- ===================================================================
-- WHERE with remotely-executable conditions
-- WHERE with remotely-executable conditions
-- ===================================================================
-- ===================================================================
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE t1 . c1 = 1 ; -- Var, OpExpr(b), Const
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE t1 . c1 = 1 ; -- Var, OpExpr(b), Const
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE t1 . c1 = 100 AND t1 . c2 = 0 ; -- BoolExpr
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE t1 . c1 = 100 AND t1 . c2 = 0 ; -- BoolExpr
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE c1 IS NULL ; -- NullTest
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE c1 IS NULL ; -- NullTest
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL ; -- NullTest
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE c1 IS NOT NULL ; -- NullTest
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE round ( abs ( c1 ) , 0 ) = 1 ; -- FuncExpr
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE round ( abs ( c1 ) , 0 ) = 1 ; -- FuncExpr
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE c1 = - c1 ; -- OpExpr(l)
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE c1 = - c1 ; -- OpExpr(l)
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE 1 = c1 ! ; -- OpExpr(r)
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE 1 = c1 ! ; -- OpExpr(r)
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE ( c1 IS NOT NULL ) IS DISTINCT FROM ( c1 IS NOT NULL ) ; -- DistinctExpr
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE ( c1 IS NOT NULL ) IS DISTINCT FROM ( c1 IS NOT NULL ) ; -- DistinctExpr
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE c1 = ANY ( ARRAY [ c2 , 1 , c1 + 0 ] ) ; -- ScalarArrayOpExpr
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE c1 = ANY ( ARRAY [ c2 , 1 , c1 + 0 ] ) ; -- ScalarArrayOpExpr
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE c1 = ( ARRAY [ c1 , c2 , 3 ] ) [ 1 ] ; -- ArrayRef
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE c1 = ( ARRAY [ c1 , c2 , 3 ] ) [ 1 ] ; -- ArrayRef
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE c6 = E ' foo '' s\\bar ' ; -- check special chars
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE c6 = E ' foo '' s\\bar ' ; -- check special chars
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 t1 WHERE c8 = ' foo ' ; -- can't be sent to remote
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 t1 WHERE c8 = ' foo ' ; -- can't be sent to remote
-- parameterized remote path for foreign table
-- parameterized remote path for foreign table
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT * FROM " S 1 " . " T 1 " a , ft2 b WHERE a . " C 1 " = 47 AND b . c1 = a . c2 ;
SELECT * FROM " S 1 " . " T 1 " a , ft2 b WHERE a . " C 1 " = 47 AND b . c1 = a . c2 ;
SELECT * FROM ft2 a , ft2 b WHERE a . c1 = 47 AND b . c1 = a . c2 ;
SELECT * FROM ft2 a , ft2 b WHERE a . c1 = 47 AND b . c1 = a . c2 ;
-- check both safe and unsafe join conditions
-- check both safe and unsafe join conditions
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT * FROM ft2 a , ft2 b
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 ) ;
WHERE a . c2 = 6 AND b . c1 = a . c1 AND a . c8 = ' foo ' AND b . c7 = upper ( a . c7 ) ;
SELECT * FROM ft2 a , ft2 b
SELECT * FROM ft2 a , ft2 b
@ -286,9 +286,9 @@ SELECT * FROM ft1 WHERE c1 = ANY (ARRAY(SELECT c1 FROM ft2 WHERE c1 < 5));
SELECT * FROM ft2 WHERE c1 = ANY ( ARRAY ( SELECT c1 FROM ft1 WHERE c1 < 5 ) ) ;
SELECT * FROM ft2 WHERE c1 = ANY ( ARRAY ( SELECT c1 FROM ft1 WHERE c1 < 5 ) ) ;
-- we should not push order by clause with volatile expressions or unsafe
-- we should not push order by clause with volatile expressions or unsafe
-- collations
-- collations
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT * FROM ft2 ORDER BY ft2 . c1 , random ( ) ;
SELECT * FROM ft2 ORDER BY ft2 . c1 , random ( ) ;
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT * FROM ft2 ORDER BY ft2 . c1 , ft2 . c3 collate " C " ;
SELECT * FROM ft2 ORDER BY ft2 . c1 , ft2 . c3 collate " C " ;
-- user-defined operator/function
-- user-defined operator/function
@ -305,18 +305,18 @@ CREATE OPERATOR === (
) ;
) ;
-- built-in operators and functions can be shipped for remote execution
-- built-in operators and functions can be shipped for remote execution
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = abs ( t1 . c2 ) ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = abs ( t1 . c2 ) ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = abs ( t1 . c2 ) ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = abs ( t1 . c2 ) ;
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = t1 . c2 ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = t1 . c2 ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = t1 . c2 ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = t1 . c2 ;
-- by default, user-defined ones cannot
-- by default, user-defined ones cannot
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = postgres_fdw_abs ( t1 . c2 ) ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = postgres_fdw_abs ( t1 . c2 ) ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = postgres_fdw_abs ( t1 . c2 ) ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = postgres_fdw_abs ( t1 . c2 ) ;
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = = = t1 . c2 ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = = = t1 . c2 ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = = = t1 . c2 ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = = = t1 . c2 ;
@ -326,10 +326,10 @@ ALTER EXTENSION postgres_fdw ADD OPERATOR === (int, int);
ALTER SERVER loopback OPTIONS ( ADD extensions ' postgres_fdw ' ) ;
ALTER SERVER loopback OPTIONS ( ADD extensions ' postgres_fdw ' ) ;
-- ... now they can be shipped
-- ... now they can be shipped
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = postgres_fdw_abs ( t1 . c2 ) ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = postgres_fdw_abs ( t1 . c2 ) ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = postgres_fdw_abs ( t1 . c2 ) ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = postgres_fdw_abs ( t1 . c2 ) ;
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = = = t1 . c2 ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = = = t1 . c2 ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = = = t1 . c2 ;
SELECT count ( c3 ) FROM ft1 t1 WHERE t1 . c1 = = = t1 . c2 ;
@ -342,247 +342,232 @@ ANALYZE ft4;
ANALYZE ft5 ;
ANALYZE ft5 ;
-- join two tables
-- join two tables
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- join three tables
-- join three tables
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- left outer join
-- left outer join
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- left outer join three tables
-- left outer join three tables
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- left outer join + placement of clauses.
-- left outer join + placement of clauses.
-- clauses within the nullable side are not pulled up, but top level clause on
-- clauses within the nullable side are not pulled up, but top level clause on
-- non-nullable side is pushed into non-nullable side
-- non-nullable side is pushed into non-nullable side
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- clauses within the nullable side are not pulled up, but the top level clause
-- clauses within the nullable side are not pulled up, but the top level clause
-- on nullable side is not pushed down into nullable side
-- on nullable side is not pushed down into nullable side
EXPLAIN ( COSTS false , VERBOSE )
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 )
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 ;
WHERE ( t2 . c1 < 10 OR t2 . c1 IS NULL ) AND t1 . c1 < 10 ;
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 )
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 ;
WHERE ( t2 . c1 < 10 OR t2 . c1 IS NULL ) AND t1 . c1 < 10 ;
-- right outer join
-- right outer join
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- right outer join three tables
-- right outer join three tables
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- full outer join
-- full outer join
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- full outer join with restrictions on the joining relations
-- full outer join with restrictions on the joining relations
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- full outer join + inner join
-- full outer join + inner join
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- full outer join three tables
-- full outer join three tables
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- full outer join + right outer join
-- full outer join + right outer join
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- right outer join + full outer join
-- right outer join + full outer join
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- full outer join + left outer join
-- full outer join + left outer join
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- left outer join + full outer join
-- left outer join + full outer join
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- right outer join + left outer join
-- right outer join + left outer join
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- left outer join + right outer join
-- left outer join + right outer join
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- full outer join + WHERE clause, only matched rows
-- full outer join + WHERE clause, only matched rows
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- join two tables with FOR UPDATE clause
-- join two tables with FOR UPDATE clause
-- tests whole-row reference for row marks
-- tests whole-row reference for row marks
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- join two tables with FOR SHARE clause
-- join two tables with FOR SHARE clause
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- join in CTE
-- join in CTE
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- ctid with whole-row reference
-- ctid with whole-row reference
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
-- SEMI JOIN, not pushed down
-- SEMI JOIN, not pushed down
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- ANTI JOIN, not pushed down
-- ANTI JOIN, not pushed down
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- CROSS JOIN, not pushed down
-- CROSS JOIN, not pushed down
EXPLAIN ( COSTS false , VERBOSE )
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 ;
SELECT t1 . c1 , t2 . c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1 . c1 , t2 . c1 OFFSET 100 LIMIT 10 ;
SELECT t1 . c1 , t2 . c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1 . c1 , t2 . c1 OFFSET 100 LIMIT 10 ;
SELECT t1 . c1 , t2 . c1 FROM ft1 t1 CROSS JOIN ft2 t2 ORDER BY t1 . c1 , t2 . c1 OFFSET 100 LIMIT 10 ;
-- different server, not pushed down. No result expected.
-- different server, not pushed down. No result expected.
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS
-- unsafe join conditions (c8 has a UDT), not pushed down. Practically a CROSS
-- JOIN since c8 in both tables has same value.
-- JOIN since c8 in both tables has same value.
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- unsafe conditions on one side (c8 has a UDT), not pushed down.
-- unsafe conditions on one side (c8 has a UDT), not pushed down.
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- join where unsafe to pushdown condition in WHERE clause has a column not
-- 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
-- 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
-- references from both joining sides so that the clause is not pushed down
-- into one of the joining sides.
-- into one of the joining sides.
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- Aggregate after UNION, for testing setrefs
-- Aggregate after UNION, for testing setrefs
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- join with lateral reference
-- join with lateral reference
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- create another user for permission, user mapping, effective user tests
CREATE USER view_owner ;
-- grant privileges on ft4 and ft5 to view_owner
GRANT ALL ON ft4 TO view_owner ;
GRANT ALL ON ft5 TO view_owner ;
-- prepare statement with current session user
PREPARE join_stmt AS 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 ;
EXPLAIN ( COSTS OFF , VERBOSE ) EXECUTE join_stmt ;
EXECUTE join_stmt ;
-- change the session user to view_owner and execute the statement. Because of
-- change in session user, the plan should get invalidated and created again.
-- The join will not be pushed down since the joining relations do not have a
-- valid user mapping.
SET SESSION ROLE view_owner ;
EXPLAIN ( COSTS OFF , VERBOSE ) EXECUTE join_stmt ;
RESET ROLE ;
DEALLOCATE join_stmt ;
CREATE VIEW v_ft5 AS SELECT * FROM ft5 ;
-- change owner of v_ft5 to view_owner so that the effective user for scan on
-- ft5 is view_owner and not the current user.
ALTER VIEW v_ft5 OWNER TO view_owner ;
-- create a public user mapping for loopback server
-- drop user mapping for current_user.
DROP USER MAPPING FOR CURRENT_USER SERVER loopback ;
CREATE USER MAPPING FOR PUBLIC SERVER loopback ;
-- different effective user for permission check, but same user mapping for the
-- joining sides, join pushed down, no result expected.
PREPARE join_stmt AS SELECT t1 . c1 , t2 . c1 FROM ft5 t1 JOIN v_ft5 t2 ON ( t1 . c1 = t2 . c1 ) ORDER BY t1 . c1 , t2 . c1 OFFSET 100 LIMIT 10 ;
EXPLAIN ( COSTS false , VERBOSE ) EXECUTE join_stmt ;
EXECUTE join_stmt ;
-- create user mapping for view_owner and execute the prepared statement
-- the join should not be pushed down since joining relations now use two
-- different user mappings
CREATE USER MAPPING FOR view_owner SERVER loopback ;
EXPLAIN ( COSTS false , VERBOSE ) EXECUTE join_stmt ;
EXECUTE join_stmt ;
-- If a sub-join can't be pushed down, upper level join shouldn't be either.
EXPLAIN ( COSTS false , VERBOSE )
SELECT t1 . c1 , t2 . c1 FROM ( ft5 t1 JOIN v_ft5 t2 ON ( t1 . c1 = t2 . c1 ) ) left join ( ft5 t3 JOIN v_ft5 t4 ON ( t3 . c1 = t4 . c1 ) ) ON ( t1 . c1 = t3 . c1 ) ;
-- non-Var items in targelist of the nullable rel of a join preventing
-- non-Var items in targelist of the nullable rel of a join preventing
-- push-down in some cases
-- push-down in some cases
-- unable to push {ft1, ft2}
-- unable to push {ft1, ft2}
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- ok to push {ft1, ft2} but not {ft1, ft2, ft4}
-- ok to push {ft1, ft2} but not {ft1, ft2, ft4}
EXPLAIN ( COSTS false , VERBOSE )
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 ;
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 ;
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 ;
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 ;
-- recreate the dropped user mapping for further tests
CREATE USER MAPPING FOR CURRENT_USER SERVER loopback ;
DROP USER MAPPING FOR PUBLIC SERVER loopback ;
-- join with nullable side with some columns with null values
-- join with nullable side with some columns with null values
UPDATE ft5 SET c3 = null where c1 % 9 = 0 ;
UPDATE ft5 SET c3 = null where c1 % 9 = 0 ;
EXPLAIN VERBOSE 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 ;
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 ;
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 ;
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 ;
-- 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
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 ;
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
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 ;
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
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 ;
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
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 ;
ALTER VIEW v4 OWNER TO regress_view_owner ;
-- cleanup
DROP OWNED BY regress_view_owner ;
DROP ROLE regress_view_owner ;
-- ===================================================================
-- ===================================================================
-- parameterized queries
-- parameterized queries
-- ===================================================================
-- ===================================================================
-- simple join
-- 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 ;
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 false ) EXECUTE st1 ( 1 , 2 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st1 ( 1 , 2 ) ;
EXECUTE st1 ( 1 , 1 ) ;
EXECUTE st1 ( 1 , 1 ) ;
EXECUTE st1 ( 101 , 101 ) ;
EXECUTE st1 ( 101 , 101 ) ;
-- subquery using stable function (can't be sent to remote)
-- 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 ;
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 false ) EXECUTE st2 ( 10 , 20 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st2 ( 10 , 20 ) ;
EXECUTE st2 ( 10 , 20 ) ;
EXECUTE st2 ( 10 , 20 ) ;
EXECUTE st2 ( 101 , 121 ) ;
EXECUTE st2 ( 101 , 121 ) ;
-- subquery using immutable function (can be sent to remote)
-- 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 ;
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 false ) EXECUTE st3 ( 10 , 20 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st3 ( 10 , 20 ) ;
EXECUTE st3 ( 10 , 20 ) ;
EXECUTE st3 ( 10 , 20 ) ;
EXECUTE st3 ( 20 , 30 ) ;
EXECUTE st3 ( 20 , 30 ) ;
-- custom plan should be chosen initially
-- custom plan should be chosen initially
PREPARE st4 ( int ) AS SELECT * FROM ft1 t1 WHERE t1 . c1 = $ 1 ;
PREPARE st4 ( int ) AS SELECT * FROM ft1 t1 WHERE t1 . c1 = $ 1 ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st4 ( 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st4 ( 1 ) ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st4 ( 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st4 ( 1 ) ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st4 ( 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st4 ( 1 ) ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st4 ( 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st4 ( 1 ) ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st4 ( 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st4 ( 1 ) ;
-- once we try it enough times, should switch to generic plan
-- once we try it enough times, should switch to generic plan
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st4 ( 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st4 ( 1 ) ;
-- value of $1 should not be sent to remote
-- 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 ;
PREPARE st5 ( user_enum , int ) AS SELECT * FROM ft1 t1 WHERE c8 = $ 1 and c1 = $ 2 ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS false ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXPLAIN ( VERBOSE , COSTS OFF ) EXECUTE st5 ( ' foo ' , 1 ) ;
EXECUTE st5 ( ' foo ' , 1 ) ;
EXECUTE st5 ( ' foo ' , 1 ) ;
-- cleanup
-- cleanup
@ -593,16 +578,16 @@ DEALLOCATE st4;
DEALLOCATE st5 ;
DEALLOCATE st5 ;
-- System columns, except ctid, should not be sent to remote
-- System columns, except ctid, should not be sent to remote
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT * FROM ft1 t1 WHERE t1 . tableoid = ' pg_class ' : : regclass LIMIT 1 ;
SELECT * FROM ft1 t1 WHERE t1 . tableoid = ' pg_class ' : : regclass LIMIT 1 ;
SELECT * FROM ft1 t1 WHERE t1 . tableoid = ' ft1 ' : : regclass LIMIT 1 ;
SELECT * FROM ft1 t1 WHERE t1 . tableoid = ' ft1 ' : : regclass LIMIT 1 ;
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT tableoid : : regclass , * FROM ft1 t1 LIMIT 1 ;
SELECT tableoid : : regclass , * FROM ft1 t1 LIMIT 1 ;
SELECT tableoid : : regclass , * FROM ft1 t1 LIMIT 1 ;
SELECT tableoid : : regclass , * FROM ft1 t1 LIMIT 1 ;
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT * FROM ft1 t1 WHERE t1 . ctid = ' (0,2) ' ;
SELECT * FROM ft1 t1 WHERE t1 . ctid = ' (0,2) ' ;
SELECT * FROM ft1 t1 WHERE t1 . ctid = ' (0,2) ' ;
SELECT * FROM ft1 t1 WHERE t1 . ctid = ' (0,2) ' ;
EXPLAIN ( VERBOSE , COSTS false )
EXPLAIN ( VERBOSE , COSTS OFF )
SELECT ctid , * FROM ft1 t1 LIMIT 1 ;
SELECT ctid , * FROM ft1 t1 LIMIT 1 ;
SELECT ctid , * FROM ft1 t1 LIMIT 1 ;
SELECT ctid , * FROM ft1 t1 LIMIT 1 ;
@ -764,13 +749,13 @@ select c2, count(*) from "S 1"."T 1" where c2 < 500 group by 1 order by 1;
-- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs
-- Above DMLs add data with c6 as NULL in ft1, so test ORDER BY NULLS LAST and NULLs
-- FIRST behavior here.
-- FIRST behavior here.
-- ORDER BY DESC NULLS LAST options
-- ORDER BY DESC NULLS LAST options
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 ORDER BY c6 DESC NULL S LAST , c1 OFFSET 795 LIMIT 10 ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 ORDER BY c6 DESC NULL S LAST , c1 OFFSET 795 LIMIT 10 ;
SELECT * FROM ft1 ORDER BY c6 DESC NULL S LAST , c1 OFFSET 795 LIMIT 10 ;
SELECT * FROM ft1 ORDER BY c6 DESC NULL S LAST , c1 OFFSET 795 LIMIT 10 ;
-- ORDER BY DESC NULLS FIRST options
-- ORDER BY DESC NULLS FIRST options
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 ORDER BY c6 DESC NULL S FIRST , c1 OFFSET 15 LIMIT 10 ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 ORDER BY c6 DESC NULL S FIRST , c1 OFFSET 15 LIMIT 10 ;
SELECT * FROM ft1 ORDER BY c6 DESC NULL S FIRST , c1 OFFSET 15 LIMIT 10 ;
SELECT * FROM ft1 ORDER BY c6 DESC NULL S FIRST , c1 OFFSET 15 LIMIT 10 ;
-- ORDER BY ASC NULLS FIRST options
-- ORDER BY ASC NULLS FIRST options
EXPLAIN ( VERBOSE , COSTS false ) SELECT * FROM ft1 ORDER BY c6 ASC NULL S FIRST , c1 OFFSET 15 LIMIT 10 ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT * FROM ft1 ORDER BY c6 ASC NULL S FIRST , c1 OFFSET 15 LIMIT 10 ;
SELECT * FROM ft1 ORDER BY c6 ASC NULL S FIRST , c1 OFFSET 15 LIMIT 10 ;
SELECT * FROM ft1 ORDER BY c6 ASC NULL S FIRST , c1 OFFSET 15 LIMIT 10 ;
-- ===================================================================
-- ===================================================================
@ -779,10 +764,10 @@ SELECT * FROM ft1 ORDER BY c6 ASC NULLS FIRST, c1 OFFSET 15 LIMIT 10;
-- Consistent check constraints provide consistent results
-- Consistent check constraints provide consistent results
ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK ( c2 > = 0 ) ;
ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2positive CHECK ( c2 > = 0 ) ;
EXPLAIN ( VERBOSE , COSTS false ) SELECT count ( * ) FROM ft1 WHERE c2 < 0 ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT count ( * ) FROM ft1 WHERE c2 < 0 ;
SELECT count ( * ) FROM ft1 WHERE c2 < 0 ;
SELECT count ( * ) FROM ft1 WHERE c2 < 0 ;
SET constraint_exclusion = ' on ' ;
SET constraint_exclusion = ' on ' ;
EXPLAIN ( VERBOSE , COSTS false ) SELECT count ( * ) FROM ft1 WHERE c2 < 0 ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT count ( * ) FROM ft1 WHERE c2 < 0 ;
SELECT count ( * ) FROM ft1 WHERE c2 < 0 ;
SELECT count ( * ) FROM ft1 WHERE c2 < 0 ;
RESET constraint_exclusion ;
RESET constraint_exclusion ;
-- check constraint is enforced on the remote side, not locally
-- check constraint is enforced on the remote side, not locally
@ -792,10 +777,10 @@ ALTER FOREIGN TABLE ft1 DROP CONSTRAINT ft1_c2positive;
-- But inconsistent check constraints provide inconsistent results
-- But inconsistent check constraints provide inconsistent results
ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK ( c2 < 0 ) ;
ALTER FOREIGN TABLE ft1 ADD CONSTRAINT ft1_c2negative CHECK ( c2 < 0 ) ;
EXPLAIN ( VERBOSE , COSTS false ) SELECT count ( * ) FROM ft1 WHERE c2 > = 0 ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT count ( * ) FROM ft1 WHERE c2 > = 0 ;
SELECT count ( * ) FROM ft1 WHERE c2 > = 0 ;
SELECT count ( * ) FROM ft1 WHERE c2 > = 0 ;
SET constraint_exclusion = ' on ' ;
SET constraint_exclusion = ' on ' ;
EXPLAIN ( VERBOSE , COSTS false ) SELECT count ( * ) FROM ft1 WHERE c2 > = 0 ;
EXPLAIN ( VERBOSE , COSTS OFF ) SELECT count ( * ) FROM ft1 WHERE c2 > = 0 ;
SELECT count ( * ) FROM ft1 WHERE c2 > = 0 ;
SELECT count ( * ) FROM ft1 WHERE c2 > = 0 ;
RESET constraint_exclusion ;
RESET constraint_exclusion ;
-- local check constraint is not actually enforced
-- local check constraint is not actually enforced
@ -1360,7 +1345,3 @@ WHERE ftrelid = 'table30000'::regclass
AND ftoptions @ > array [ ' fetch_size=60000 ' ] ;
AND ftoptions @ > array [ ' fetch_size=60000 ' ] ;
ROLLBACK ;
ROLLBACK ;
-- Cleanup
DROP OWNED BY view_owner ;
DROP USER view_owner ;