Commit 83204e10 authored by Tom Lane's avatar Tom Lane

Fix contrib/postgres_fdw to handle multiple join conditions properly.

The previous coding supposed that it could consider just a single join
condition in any one parameterized path for the foreign table.  But in
reality, the parameterized-path machinery forces all join clauses that are
"movable to" the foreign table to be evaluated at that node; including
clauses that we might not consider safe to send across.  Such cases would
result in an Assert failure in an assert-enabled build, and otherwise in
sending an unsafe clause to the foreign server, which might result in
errors or silently-wrong answers.  A lesser problem was that the
cost/rowcount estimates generated for the parameterized path failed to
account for any additional join quals that get assigned to the scan.

To fix, rewrite postgresGetForeignPaths so that it correctly collects all
the movable quals for any one outer relation when generating parameterized
paths; we'll now generate just one path per outer relation not one per join
qual.  Also fix bogus assumptions in postgresGetForeignPlan and
estimate_path_cost_size that only safe-to-send join quals will be
presented.

Based on complaint from Etsuro Fujita that the path costs were being
miscalculated, though this is significantly different from his proposed
patch.
parent 4ea2e2d4
...@@ -134,14 +134,15 @@ static void deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context); ...@@ -134,14 +134,15 @@ static void deparseArrayExpr(ArrayExpr *node, deparse_expr_cxt *context);
/* /*
* Examine each restriction clause in baserel's baserestrictinfo list, * Examine each qual clause in input_conds, and classify them into two groups,
* and classify them into two groups, which are returned as two lists: * which are returned as two lists:
* - remote_conds contains expressions that can be evaluated remotely * - remote_conds contains expressions that can be evaluated remotely
* - local_conds contains expressions that can't be evaluated remotely * - local_conds contains expressions that can't be evaluated remotely
*/ */
void void
classifyConditions(PlannerInfo *root, classifyConditions(PlannerInfo *root,
RelOptInfo *baserel, RelOptInfo *baserel,
List *input_conds,
List **remote_conds, List **remote_conds,
List **local_conds) List **local_conds)
{ {
...@@ -150,7 +151,7 @@ classifyConditions(PlannerInfo *root, ...@@ -150,7 +151,7 @@ classifyConditions(PlannerInfo *root,
*remote_conds = NIL; *remote_conds = NIL;
*local_conds = NIL; *local_conds = NIL;
foreach(lc, baserel->baserestrictinfo) foreach(lc, input_conds)
{ {
RestrictInfo *ri = (RestrictInfo *) lfirst(lc); RestrictInfo *ri = (RestrictInfo *) lfirst(lc);
......
This diff is collapsed.
...@@ -41,6 +41,7 @@ extern int ExtractConnectionOptions(List *defelems, ...@@ -41,6 +41,7 @@ extern int ExtractConnectionOptions(List *defelems,
/* in deparse.c */ /* in deparse.c */
extern void classifyConditions(PlannerInfo *root, extern void classifyConditions(PlannerInfo *root,
RelOptInfo *baserel, RelOptInfo *baserel,
List *input_conds,
List **remote_conds, List **remote_conds,
List **local_conds); List **local_conds);
extern bool is_foreign_expr(PlannerInfo *root, extern bool is_foreign_expr(PlannerInfo *root,
......
...@@ -194,6 +194,12 @@ EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c8 = 'foo'; -- can't ...@@ -194,6 +194,12 @@ EXPLAIN (VERBOSE, COSTS false) SELECT * FROM ft1 t1 WHERE c8 = 'foo'; -- can't
EXPLAIN (VERBOSE, COSTS false) EXPLAIN (VERBOSE, COSTS false)
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;
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
EXPLAIN (VERBOSE, COSTS false)
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);
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);
-- =================================================================== -- ===================================================================
-- parameterized queries -- parameterized queries
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment