0001-postgres_fdw-should-avoid-sorted-paths-which-don-t-p.patch
text/x-diff
Filename: 0001-postgres_fdw-should-avoid-sorted-paths-which-don-t-p.patch
Type: text/x-diff
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: postgres_fdw should avoid sorted paths which don't provide all required vars
| File | + | − |
|---|---|---|
| contrib/postgres_fdw/postgres_fdw.c | 56 | 0 |
From e0cf7be1682feb8dbca80adefbaac06ef8315ba4 Mon Sep 17 00:00:00 2001
From: Alexander Pyhalov <a.pyhalov@postgrespro.ru>
Date: Tue, 9 Aug 2022 14:47:16 +0300
Subject: [PATCH] postgres_fdw should avoid sorted paths which don't provide
all required vars
---
contrib/postgres_fdw/postgres_fdw.c | 56 +++++++++++++++++++++++++++++
1 file changed, 56 insertions(+)
diff --git a/contrib/postgres_fdw/postgres_fdw.c b/contrib/postgres_fdw/postgres_fdw.c
index 16320170cee..e21ddd7485f 100644
--- a/contrib/postgres_fdw/postgres_fdw.c
+++ b/contrib/postgres_fdw/postgres_fdw.c
@@ -541,6 +541,7 @@ static void merge_fdw_options(PgFdwRelationInfo *fpinfo,
const PgFdwRelationInfo *fpinfo_o,
const PgFdwRelationInfo *fpinfo_i);
static int get_batch_size_option(Relation rel);
+static bool path_provides_local_vars(Path *path, PgFdwRelationInfo *fpinfo);
/*
@@ -5775,6 +5776,54 @@ foreign_join_ok(PlannerInfo *root, RelOptInfo *joinrel, JoinType jointype,
return true;
}
+/*
+ * Determines if all vars, used by fpinfo->local_conds,
+ * are provided by path.
+ */
+static bool
+path_provides_local_vars(Path *path, PgFdwRelationInfo *fpinfo)
+{
+ List *vars_provided;
+ ListCell *lc1;
+ ListCell *lc2;
+ ListCell *lc3;
+
+ if (path == NULL)
+ return false;
+
+ /* Get all vars, provided by path */
+ vars_provided = pull_var_clause((Node *) path->pathtarget->exprs, PVC_INCLUDE_PLACEHOLDERS);
+
+ foreach(lc1, fpinfo->local_conds)
+ {
+ RestrictInfo *ri = (RestrictInfo *) lfirst(lc1);
+ List *vars_used;
+
+ /* Get vars, used by this restriction clause */
+ vars_used = pull_var_clause((Node *) ri->clause, PVC_INCLUDE_PLACEHOLDERS);
+ foreach(lc2, vars_used)
+ {
+ Var *used = lfirst(lc2);
+ bool found = false;
+
+ foreach(lc3, vars_provided)
+ {
+ Var *provided = lfirst(lc3);
+
+ if (provided->varno == used->varno && provided->varattno == used->varattno)
+ {
+ found = true;
+ break;
+ }
+ }
+ if (!found)
+ return false;
+ }
+ }
+
+ return true;
+}
+
static void
add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
Path *epq_path)
@@ -5812,6 +5861,13 @@ add_paths_with_pathkeys_for_rel(PlannerInfo *root, RelOptInfo *rel,
useful_pathkeys,
-1.0);
+ /*
+ * Sorted path should provide all vars needed by local conditions or
+ * we'll not be able to use it
+ */
+ if (sorted_epq_path != NULL && !path_provides_local_vars(sorted_epq_path, (PgFdwRelationInfo *) rel->fdw_private))
+ return;
+
if (IS_SIMPLE_REL(rel))
add_path(rel, (Path *)
create_foreignscan_path(root, rel,
--
2.34.1