sje_skip_cross_lateral_vars.patch
application/octet-stream
Filename: sje_skip_cross_lateral_vars.patch
Type: application/octet-stream
Part: 0
Message:
Re: Removing unneeded self joins
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
| File | + | − |
|---|---|---|
| src/backend/optimizer/plan/analyzejoins.c | 35 | 0 |
diff --git a/src/backend/optimizer/plan/analyzejoins.c b/src/backend/optimizer/plan/analyzejoins.c
index 506fccd20c9..3304b0ea547 100644
--- a/src/backend/optimizer/plan/analyzejoins.c
+++ b/src/backend/optimizer/plan/analyzejoins.c
@@ -29,6 +29,7 @@
#include "optimizer/pathnode.h"
#include "optimizer/paths.h"
#include "optimizer/planmain.h"
+#include "optimizer/placeholder.h"
#include "optimizer/restrictinfo.h"
#include "utils/lsyscache.h"
@@ -2101,6 +2102,36 @@ match_unique_clauses(PlannerInfo *root, RelOptInfo *outer, List *uclauses,
return true;
}
+static bool
+check_lateral_vars(PlannerInfo *root, RelOptInfo *inner, RelOptInfo *outer)
+{
+ ListCell *lc;
+
+ foreach(lc, inner->lateral_vars)
+ {
+ Node *node = (Node *) lfirst(lc);
+
+ if (IsA(node, Var))
+ {
+ Var *var = (Var *) node;
+
+ if (var->varno == outer->relid)
+ return false;
+ }
+ else if (IsA(node, PlaceHolderVar))
+ {
+ PlaceHolderVar *phv = (PlaceHolderVar *) node;
+ PlaceHolderInfo *phinfo = find_placeholder_info(root, phv);
+
+ if (bms_is_member(outer->relid, phinfo->ph_eval_at))
+ return false;
+ }
+ else
+ Assert(false);
+ }
+ return true;
+}
+
/*
* Find and remove unique self joins in a group of base relations that have
* the same Oid.
@@ -2255,6 +2286,10 @@ remove_self_joins_one_group(PlannerInfo *root, Relids relids)
if (!match_unique_clauses(root, inner, uclauses, outer->relid))
continue;
+ if (!check_lateral_vars(root, outer, inner) ||
+ !check_lateral_vars(root, inner, outer))
+ continue;
+
/*
* We can remove either relation, so remove the inner one in order
* to simplify this loop.