From 9bc8ce0021869cef0ce6029d8aaf2a363434e268 Mon Sep 17 00:00:00 2001 From: "Andrey V. Lepikhov" Date: Wed, 6 Jul 2022 14:44:56 +0300 Subject: [PATCH 1/6] Expand the duties of check_mergejoinable to check non-equal btree operator as well to support the EC Filter function. A new field named btreeineqopfamilies is added into RestictInfo and it is set with the same round syscache search for check_mergejoinable. because of this, check_mergejoinable is renamed to check_btreeable. The bad part of this is it only works for opclause so far. --- src/backend/optimizer/plan/initsplan.c | 35 +++++++++++------------ src/backend/optimizer/util/restrictinfo.c | 1 + src/backend/utils/cache/lsyscache.c | 35 +++++++++++++++++++++++ src/include/nodes/pathnodes.h | 1 + src/include/utils/lsyscache.h | 1 + 5 files changed, 55 insertions(+), 18 deletions(-) diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 023efbaf09..fa2bfbfb72 100644 --- a/src/backend/optimizer/plan/initsplan.c +++ b/src/backend/optimizer/plan/initsplan.c @@ -76,7 +76,7 @@ static bool check_outerjoin_delay(PlannerInfo *root, Relids *relids_p, static bool check_equivalence_delay(PlannerInfo *root, RestrictInfo *restrictinfo); static bool check_redundant_nullability_qual(PlannerInfo *root, Node *clause); -static void check_mergejoinable(RestrictInfo *restrictinfo); +static void check_btreeable(RestrictInfo *restrictinfo); static void check_hashjoinable(RestrictInfo *restrictinfo); static void check_memoizable(RestrictInfo *restrictinfo); @@ -1874,8 +1874,11 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause, * We check "mergejoinability" of every clause, not only join clauses, * because we want to know about equivalences between vars of the same * relation, or between vars and consts. + * + * We also checked the btree-able properity at the same round of checking + * mergejoinability to support ec filter function. */ - check_mergejoinable(restrictinfo); + check_btreeable(restrictinfo); /* * If it is a true equivalence clause, send it to the EquivalenceClass @@ -2389,7 +2392,7 @@ process_implied_equality(PlannerInfo *root, * from an EquivalenceClass; but we could have reduced the original clause * to a constant. */ - check_mergejoinable(restrictinfo); + check_btreeable(restrictinfo); /* * Note we don't do initialize_mergeclause_eclasses(); the caller can @@ -2456,8 +2459,8 @@ build_implied_join_equality(PlannerInfo *root, NULL, /* outer_relids */ nullable_relids); /* nullable_relids */ - /* Set mergejoinability/hashjoinability flags */ - check_mergejoinable(restrictinfo); + /* Set btreeability/hashjoinability flags */ + check_btreeable(restrictinfo); check_hashjoinable(restrictinfo); check_memoizable(restrictinfo); @@ -2641,20 +2644,16 @@ match_foreign_keys_to_quals(PlannerInfo *root) *****************************************************************************/ /* - * check_mergejoinable - * If the restrictinfo's clause is mergejoinable, set the mergejoin - * info fields in the restrictinfo. - * - * Currently, we support mergejoin for binary opclauses where - * the operator is a mergejoinable operator. The arguments can be - * anything --- as long as there are no volatile functions in them. + * check_btreeable + * If the restrictinfo's clause is btreeable, set the mergejoin + * info field and btreeineq info field in the restrictinfo. btreeable + * now is a superset of mergeable. */ static void -check_mergejoinable(RestrictInfo *restrictinfo) +check_btreeable(RestrictInfo *restrictinfo) { Expr *clause = restrictinfo->clause; Oid opno; - Node *leftarg; if (restrictinfo->pseudoconstant) return; @@ -2664,11 +2663,11 @@ check_mergejoinable(RestrictInfo *restrictinfo) return; opno = ((OpExpr *) clause)->opno; - leftarg = linitial(((OpExpr *) clause)->args); - if (op_mergejoinable(opno, exprType(leftarg)) && - !contain_volatile_functions((Node *) restrictinfo)) - restrictinfo->mergeopfamilies = get_mergejoin_opfamilies(opno); + if (!contain_volatile_functions((Node *) restrictinfo)) + get_btree_opfamilies(opno, + &restrictinfo->mergeopfamilies, + &restrictinfo->btreeineqopfamilies); /* * Note: op_mergejoinable is just a hint; if we fail to find the operator diff --git a/src/backend/optimizer/util/restrictinfo.c b/src/backend/optimizer/util/restrictinfo.c index ef8df3d098..e09196d26f 100644 --- a/src/backend/optimizer/util/restrictinfo.c +++ b/src/backend/optimizer/util/restrictinfo.c @@ -201,6 +201,7 @@ make_restrictinfo_internal(PlannerInfo *root, restrictinfo->outer_selec = -1; restrictinfo->mergeopfamilies = NIL; + restrictinfo->btreeineqopfamilies = NIL; restrictinfo->left_ec = NULL; restrictinfo->right_ec = NULL; diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 1b7e11b93e..91cd813ce8 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -389,6 +389,41 @@ get_mergejoin_opfamilies(Oid opno) return result; } +/* + * TODO: get_mergejoin_opfamilies shoud be replaced with this function. + */ +void +get_btree_opfamilies(Oid opno, + List **mergeable_opfamilies, + List **unmergeable_btree_opfamilies) +{ + CatCList *catlist; + int i; + + /* + * Search pg_amop to see find out all the btree opfamilies. + */ + catlist = SearchSysCacheList1(AMOPOPID, ObjectIdGetDatum(opno)); + + for (i = 0; i < catlist->n_members; i++) + { + HeapTuple tuple = &catlist->members[i]->tuple; + Form_pg_amop aform = (Form_pg_amop) GETSTRUCT(tuple); + + if (aform->amopmethod == BTREE_AM_OID) + { + if (aform->amopstrategy == BTEqualStrategyNumber) + *mergeable_opfamilies = lappend_oid(*mergeable_opfamilies, + aform->amopfamily); + else + *unmergeable_btree_opfamilies = lappend_oid(*unmergeable_btree_opfamilies, + aform->amopfamily); + } + } + + ReleaseSysCacheList(catlist); +} + /* * get_compatible_hash_operators * Get the OID(s) of hash equality operator(s) compatible with the given diff --git a/src/include/nodes/pathnodes.h b/src/include/nodes/pathnodes.h index b88cfb8dc0..f407f1852d 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -2305,6 +2305,7 @@ typedef struct RestrictInfo * mergejoinable, else NIL */ List *mergeopfamilies; + List *btreeineqopfamilies; /* btree families except the mergeable ones */ /* * cache space for mergeclause processing; NULL if not yet set diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index b8dd27d4a9..5b5fac0397 100644 --- a/src/include/utils/lsyscache.h +++ b/src/include/utils/lsyscache.h @@ -79,6 +79,7 @@ extern bool get_ordering_op_properties(Oid opno, extern Oid get_equality_op_for_ordering_op(Oid opno, bool *reverse); extern Oid get_ordering_op_for_equality_op(Oid opno, bool use_lhs_type); extern List *get_mergejoin_opfamilies(Oid opno); +extern void get_btree_opfamilies(Oid opno, List **mergeable_opfamilies, List **unmergeable_btree_opfamilies); extern bool get_compatible_hash_operators(Oid opno, Oid *lhs_opno, Oid *rhs_opno); extern bool get_op_hash_functions(Oid opno, -- 2.37.0