From 0efd829e3c411b6733aa308d9e1267e592873005 Mon Sep 17 00:00:00 2001 From: Andy Fan Date: Mon, 7 Mar 2022 10:07:44 +0800 Subject: [PATCH v4 1/6] expand the duties of check_mergejoinable to check non-equal btree operator as well to support the EC Filter function. A new filed named btreeineqopfamilies is added in 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 | 33 ++++++++++----------- 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(+), 16 deletions(-) diff --git a/src/backend/optimizer/plan/initsplan.c b/src/backend/optimizer/plan/initsplan.c index 023efbaf092..d61419f61a5 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,16 +2644,13 @@ 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; @@ -2666,9 +2666,10 @@ check_mergejoinable(RestrictInfo *restrictinfo) 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 ef8df3d098e..e09196d26f6 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 1b7e11b93e0..91cd813ce8f 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 1f3845b3fec..3b95e4a8eae 100644 --- a/src/include/nodes/pathnodes.h +++ b/src/include/nodes/pathnodes.h @@ -2105,6 +2105,7 @@ typedef struct RestrictInfo /* valid if clause is mergejoinable, else NIL */ List *mergeopfamilies; /* opfamilies containing clause operator */ + List *btreeineqopfamilies; /* btree families except the mergeable ones */ /* cache space for mergeclause processing; NULL if not yet set */ EquivalenceClass *left_ec; /* EquivalenceClass containing lefthand */ diff --git a/src/include/utils/lsyscache.h b/src/include/utils/lsyscache.h index b8dd27d4a96..5b5fac0397c 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.21.0