diff --git a/src/backend/optimizer/path/clausesel.c b/src/backend/optimizer/path/clausesel.c index 5d51f97f219..e3de67ace3a 100644 --- a/src/backend/optimizer/path/clausesel.c +++ b/src/backend/optimizer/path/clausesel.c @@ -23,6 +23,10 @@ #include "utils/fmgroids.h" #include "utils/lsyscache.h" #include "utils/selfuncs.h" +#include "parser/parser.h" + +/* Hook for extensions to override OpExpr selectivity */ +opexpr_selectivity_hook_type opexpr_selectivity_hook = NULL; /* * Data structure for accumulating info about possible range-query @@ -844,11 +848,21 @@ clause_selectivity_ext(PlannerInfo *root, } else { - /* Estimate selectivity for a restriction clause. */ - s1 = restriction_selectivity(root, opno, - opclause->args, - opclause->inputcollid, - varRelid); + /* + * Allow extensions to override OpExpr selectivity estimation + * via the opexpr_selectivity_hook (Babelfish only). + */ + if (!(sql_dialect == SQL_DIALECT_TSQL && + opexpr_selectivity_hook && + opexpr_selectivity_hook(root, clause, varRelid, jointype, + sjinfo, use_extended_stats, &s1))) + { + /* Estimate selectivity for a restriction clause. */ + s1 = restriction_selectivity(root, opno, + opclause->args, + opclause->inputcollid, + varRelid); + } } /* diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c index c9ff71844e7..d42e13fdcf8 100644 --- a/src/backend/utils/adt/selfuncs.c +++ b/src/backend/utils/adt/selfuncs.c @@ -141,6 +141,10 @@ #include "utils/syscache.h" #include "utils/timestamp.h" #include "utils/typcache.h" +#include "parser/parser.h" + +/* Hook for extensions to override NullTest selectivity */ +nulltest_selectivity_hook_type nulltest_selectivity_hook = NULL; #define DEFAULT_PAGE_CPU_MULTIPLIER 50.0 @@ -1754,20 +1758,26 @@ nulltestsel(PlannerInfo *root, NullTestType nulltesttype, Node *arg, else { /* - * No ANALYZE stats available, so make a guess + * No ANALYZE stats available. Allow extensions to override + * NullTest selectivity via nulltest_selectivity_hook (Babelfish only). */ - switch (nulltesttype) + if (!(sql_dialect == SQL_DIALECT_TSQL && + nulltest_selectivity_hook && + nulltest_selectivity_hook(root, nulltesttype, arg, varRelid, &selec))) { - case IS_NULL: - selec = DEFAULT_UNK_SEL; - break; - case IS_NOT_NULL: - selec = DEFAULT_NOT_UNK_SEL; - break; - default: - elog(ERROR, "unrecognized nulltesttype: %d", - (int) nulltesttype); - return (Selectivity) 0; /* keep compiler quiet */ + switch (nulltesttype) + { + case IS_NULL: + selec = DEFAULT_UNK_SEL; + break; + case IS_NOT_NULL: + selec = DEFAULT_NOT_UNK_SEL; + break; + default: + elog(ERROR, "unrecognized nulltesttype: %d", + (int) nulltesttype); + return (Selectivity) 0; /* keep compiler quiet */ + } } } diff --git a/src/include/utils/selfuncs.h b/src/include/utils/selfuncs.h index fb4fa53363d..6632388d1e9 100644 --- a/src/include/utils/selfuncs.h +++ b/src/include/utils/selfuncs.h @@ -248,4 +248,21 @@ extern Selectivity scalararraysel_containment(PlannerInfo *root, Oid elemtype, bool isEquality, bool useOr, int varRelid); +/* Babelfish hooks for selectivity estimation override */ +typedef bool (*opexpr_selectivity_hook_type) (PlannerInfo *root, + Node *clause, + int varRelid, + JoinType jointype, + SpecialJoinInfo *sjinfo, + bool use_extended_stats, + Selectivity *selec); +extern PGDLLEXPORT opexpr_selectivity_hook_type opexpr_selectivity_hook; + +typedef bool (*nulltest_selectivity_hook_type) (PlannerInfo *root, + NullTestType nulltesttype, + Node *arg, + int varRelid, + Selectivity *selec); +extern PGDLLEXPORT nulltest_selectivity_hook_type nulltest_selectivity_hook; + #endif /* SELFUNCS_H */