aboutsummaryrefslogtreecommitdiff
path: root/src/backend
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/optimizer/path/joinpath.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/src/backend/optimizer/path/joinpath.c b/src/backend/optimizer/path/joinpath.c
index b0e8c94dfc3..a244300463c 100644
--- a/src/backend/optimizer/path/joinpath.c
+++ b/src/backend/optimizer/path/joinpath.c
@@ -25,6 +25,7 @@
#include "optimizer/paths.h"
#include "optimizer/placeholder.h"
#include "optimizer/planmain.h"
+#include "utils/lsyscache.h"
#include "utils/typcache.h"
/* Hook for plugins to get control in add_paths_to_joinrel() */
@@ -2266,6 +2267,20 @@ hash_inner_and_outer(PlannerInfo *root,
if (!clause_sides_match_join(restrictinfo, outerrel, innerrel))
continue; /* no good for these input relations */
+ /*
+ * If clause has the form "inner op outer", check if its operator has
+ * valid commutator. This is necessary because hashclauses in this
+ * form will get commuted in createplan.c to put the outer var on the
+ * left (see get_switched_clauses). This probably shouldn't ever
+ * fail, since hashable operators ought to have commutators, but be
+ * paranoid.
+ *
+ * The clause being hashjoinable indicates that it's an OpExpr.
+ */
+ if (!restrictinfo->outer_is_left &&
+ !OidIsValid(get_commutator(castNode(OpExpr, restrictinfo->clause)->opno)))
+ continue;
+
hashclauses = lappend(hashclauses, restrictinfo);
}
@@ -2541,6 +2556,23 @@ select_mergejoin_clauses(PlannerInfo *root,
}
/*
+ * If clause has the form "inner op outer", check if its operator has
+ * valid commutator. This is necessary because mergejoin clauses in
+ * this form will get commuted in createplan.c to put the outer var on
+ * the left (see get_switched_clauses). This probably shouldn't ever
+ * fail, since mergejoinable operators ought to have commutators, but
+ * be paranoid.
+ *
+ * The clause being mergejoinable indicates that it's an OpExpr.
+ */
+ if (!restrictinfo->outer_is_left &&
+ !OidIsValid(get_commutator(castNode(OpExpr, restrictinfo->clause)->opno)))
+ {
+ have_nonmergeable_joinclause = true;
+ continue;
+ }
+
+ /*
* Insist that each side have a non-redundant eclass. This
* restriction is needed because various bits of the planner expect
* that each clause in a merge be associable with some pathkey in a