mirror of
https://github.com/postgres/postgres.git
synced 2025-07-18 17:42:25 +03:00
Allow FDWs to push down quals without breaking EvalPlanQual rechecks.
This fixes a long-standing bug which was discovered while investigating the interaction between the new join pushdown code and the EvalPlanQual machinery: if a ForeignScan appears on the inner side of a paramaterized nestloop, an EPQ recheck would re-return the original tuple even if it no longer satisfied the pushed-down quals due to changed parameter values. This fix adds a new member to ForeignScan and ForeignScanState and a new argument to make_foreignscan, and requires changes to FDWs which push down quals to populate that new argument with a list of quals they have chosen to push down. Therefore, I'm only back-patching to 9.5, even though the bug is not new in 9.5. Etsuro Fujita, reviewed by me and by Kyotaro Horiguchi.
This commit is contained in:
@ -2153,6 +2153,9 @@ create_foreignscan_plan(PlannerInfo *root, ForeignPath *best_path,
|
||||
replace_nestloop_params(root, (Node *) scan_plan->scan.plan.qual);
|
||||
scan_plan->fdw_exprs = (List *)
|
||||
replace_nestloop_params(root, (Node *) scan_plan->fdw_exprs);
|
||||
scan_plan->fdw_recheck_quals = (List *)
|
||||
replace_nestloop_params(root,
|
||||
(Node *) scan_plan->fdw_recheck_quals);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -3738,7 +3741,8 @@ make_foreignscan(List *qptlist,
|
||||
Index scanrelid,
|
||||
List *fdw_exprs,
|
||||
List *fdw_private,
|
||||
List *fdw_scan_tlist)
|
||||
List *fdw_scan_tlist,
|
||||
List *fdw_recheck_quals)
|
||||
{
|
||||
ForeignScan *node = makeNode(ForeignScan);
|
||||
Plan *plan = &node->scan.plan;
|
||||
@ -3754,6 +3758,7 @@ make_foreignscan(List *qptlist,
|
||||
node->fdw_exprs = fdw_exprs;
|
||||
node->fdw_private = fdw_private;
|
||||
node->fdw_scan_tlist = fdw_scan_tlist;
|
||||
node->fdw_recheck_quals = fdw_recheck_quals;
|
||||
/* fs_relids will be filled in by create_foreignscan_plan */
|
||||
node->fs_relids = NULL;
|
||||
/* fsSystemCol will be filled in by create_foreignscan_plan */
|
||||
|
@ -1133,13 +1133,15 @@ set_foreignscan_references(PlannerInfo *root,
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Adjust tlist, qual, fdw_exprs in the standard way */
|
||||
/* Adjust tlist, qual, fdw_exprs, etc. in the standard way */
|
||||
fscan->scan.plan.targetlist =
|
||||
fix_scan_list(root, fscan->scan.plan.targetlist, rtoffset);
|
||||
fscan->scan.plan.qual =
|
||||
fix_scan_list(root, fscan->scan.plan.qual, rtoffset);
|
||||
fscan->fdw_exprs =
|
||||
fix_scan_list(root, fscan->fdw_exprs, rtoffset);
|
||||
fscan->fdw_recheck_quals =
|
||||
fix_scan_list(root, fscan->fdw_recheck_quals, rtoffset);
|
||||
}
|
||||
|
||||
/* Adjust fs_relids if needed */
|
||||
|
@ -2394,10 +2394,18 @@ finalize_plan(PlannerInfo *root, Plan *plan, Bitmapset *valid_params,
|
||||
break;
|
||||
|
||||
case T_ForeignScan:
|
||||
finalize_primnode((Node *) ((ForeignScan *) plan)->fdw_exprs,
|
||||
&context);
|
||||
/* We assume fdw_scan_tlist cannot contain Params */
|
||||
context.paramids = bms_add_members(context.paramids, scan_params);
|
||||
{
|
||||
ForeignScan *fscan = (ForeignScan *) plan;
|
||||
|
||||
finalize_primnode((Node *) fscan->fdw_exprs,
|
||||
&context);
|
||||
finalize_primnode((Node *) fscan->fdw_recheck_quals,
|
||||
&context);
|
||||
|
||||
/* We assume fdw_scan_tlist cannot contain Params */
|
||||
context.paramids = bms_add_members(context.paramids,
|
||||
scan_params);
|
||||
}
|
||||
break;
|
||||
|
||||
case T_CustomScan:
|
||||
|
Reference in New Issue
Block a user