diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/optimizer/path/joinpath.c | 32 |
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 |