145 int *relid_subplan_map,
156 List *source_stepids,
161 Expr *clause,
Expr *partkey,
int partkeyidx,
162 bool *clause_is_not_null,
204 Expr *expr,
int stateidx,
228 int *relid_subplan_map;
245 relid_subplan_map =
palloc0(
sizeof(
int) *
root->simple_rel_array_size);
248 foreach(lc, subpaths)
273 appinfo =
root->append_rel_array[prel->
relid];
279 if (prel == parentrel)
294 relid_subplan_map[pathrel->
relid] =
i;
305 foreach(lc, allpartrelids)
318 if (pinfolist !=
NIL)
320 prunerelinfos =
lappend(prunerelinfos, pinfolist);
321 allmatchedsubplans =
bms_join(matchedsubplans,
326 pfree(relid_subplan_map);
332 if (prunerelinfos ==
NIL)
402 foreach(lc, allpartrelids)
407 if (targetpart == currtarget)
411 lfirst(lc) = currpartrelids;
412 return allpartrelids;
416 return lappend(allpartrelids, partrelids);
441 int *relid_subplan_map,
446 bool doruntimeprune =
false;
447 int *relid_subpart_map;
461 relid_subpart_map =
palloc0(
sizeof(
int) *
root->simple_rel_array_size);
470 List *initial_pruning_steps;
471 List *exec_pruning_steps;
483 Assert(rti < root->simple_rel_array_size);
484 relid_subpart_map[rti] =
i++;
493 targetpart = subpart;
518 partprunequal = prunequal;
527 partprunequal = (
List *)
564 initial_pruning_steps =
context.steps;
566 initial_pruning_steps =
NIL;
584 exec_pruning_steps =
context.steps;
594 exec_pruning_steps =
NIL;
599 exec_pruning_steps =
NIL;
603 if (initial_pruning_steps || exec_pruning_steps)
604 doruntimeprune =
true;
614 pinfolist =
lappend(pinfolist, pinfo);
620 pfree(relid_subpart_map);
632 foreach(lc, pinfolist)
637 int nparts = subpart->
nparts;
648 subplan_map = (
int *)
palloc(nparts *
sizeof(
int));
649 memset(subplan_map, -1, nparts *
sizeof(
int));
650 subpart_map = (
int *)
palloc(nparts *
sizeof(
int));
651 memset(subpart_map, -1, nparts *
sizeof(
int));
653 present_parts = NULL;
664 subplan_map[
i] = subplanidx = relid_subplan_map[partrel->
relid] - 1;
665 subpart_map[
i] = subpartidx = relid_subpart_map[partrel->
relid] - 1;
674 else if (subpartidx >= 0)
688 pinfo->subplan_map = subplan_map;
689 pinfo->subpart_map = subpart_map;
690 pinfo->relid_map = relid_map;
693 pfree(relid_subpart_map);
695 *matchedsubplans = subplansfound;
757 Assert(rel->part_scheme != NULL);
779 pruning_steps = gcontext.
steps;
782 if (pruning_steps ==
NIL)
786 context.strategy = rel->part_scheme->strategy;
787 context.partnatts = rel->part_scheme->partnatts;
789 context.boundinfo = rel->boundinfo;
790 context.partcollation = rel->part_scheme->partcollation;
791 context.partsupfunc = rel->part_scheme->partsupfunc;
843 foreach(lc, pruning_steps)
849 case T_PartitionPruneStepOp:
855 case T_PartitionPruneStepCombine:
856 results[step->step_id] =
863 elog(
ERROR,
"invalid pruning step type: %d",
873 final_result = results[num_steps - 1];
874 Assert(final_result != NULL);
882 Assert(i < context->boundinfo->nindexes);
883 partindex =
context->boundinfo->indexes[
i];
968 bool generate_opsteps =
false;
991 memset(keyclauses, 0,
sizeof(keyclauses));
1003 (((
Const *) clause)->constisnull ||
1006 context->contradictory =
true;
1024 bool all_args_contradictory =
true;
1040 bool arg_contradictory;
1045 arg_contradictory =
context->contradictory;
1047 context->contradictory =
false;
1049 if (arg_contradictory)
1055 all_args_contradictory =
false;
1057 if (argsteps !=
NIL)
1088 if (all_args_contradictory)
1090 context->contradictory =
true;
1094 if (arg_stepids !=
NIL)
1100 result =
lappend(result, step);
1127 if (argsteps !=
NIL)
1147 bool clause_is_not_null =
false;
1153 &clause_is_not_null,
1154 &pc, &clause_steps))
1165 context->contradictory =
true;
1168 generate_opsteps =
true;
1169 keyclauses[
i] =
lappend(keyclauses[
i], pc);
1173 if (!clause_is_not_null)
1180 keyclauses[
i] !=
NIL)
1182 context->contradictory =
true;
1192 context->contradictory =
true;
1206 context->contradictory =
true;
1259 false,
NIL,
NIL, nullkeys);
1260 result =
lappend(result, step);
1262 else if (generate_opsteps)
1277 result =
lappend(result, step);
1299 result =
lappend(result,
final);
1329 opstep->
exprs = exprs;
1347 List *source_stepids,
1393 memset(btree_clauses, 0,
sizeof(btree_clauses));
1394 memset(hash_clauses, 0,
sizeof(hash_clauses));
1397 List *clauselist = keyclauses[
i];
1398 bool consider_next_key =
true;
1417 foreach(lc, clauselist)
1446 consider_next_key =
false;
1451 elog(
ERROR,
"invalid clause for hash partitioning");
1457 elog(
ERROR,
"invalid partition strategy: %c",
1467 if (!consider_next_key)
1502 foreach(lc, btree_clauses[strat])
1511 bool prefix_valid =
true;
1512 bool pk_has_clauses;
1545 for (keyno = 0; keyno < pc->
keyno; keyno++)
1547 pk_has_clauses =
false;
1557 if (eqpc->
keyno == keyno)
1559 prefix =
lappend(prefix, eqpc);
1560 pk_has_clauses =
true;
1582 if (lepc->
keyno == keyno)
1584 prefix =
lappend(prefix, lepc);
1585 pk_has_clauses =
true;
1608 if (gepc->
keyno == keyno)
1610 prefix =
lappend(prefix, gepc);
1611 pk_has_clauses =
true;
1626 if (!pk_has_clauses)
1628 prefix_valid =
false;
1672 if (eq_clauses !=
NIL)
1686 pc =
llast(eq_clauses);
1693 last_keyno = pc->
keyno;
1694 foreach(lc, eq_clauses)
1697 if (pc->
keyno == last_keyno)
1738 elog(
ERROR,
"invalid partition strategy: %c",
1755 #define PartCollMatchesExprColl(partcoll, exprcoll) \
1756 ((partcoll) == InvalidOid || (partcoll) == (exprcoll))
1791 Expr *clause,
Expr *partkey,
int partkeyidx,
1793 List **clause_steps)
1848 nulltest->argisrow =
false;
1851 new_clauses =
list_make2(new_booltest, nulltest);
1859 else if (*clause_steps ==
NIL)
1865 partclause->
keyno = partkeyidx;
1867 partclause->
opno = BooleanEqualOperator;
1869 partclause->
expr = expr;
1884 *clause_is_not_null = notclause;
1899 bool is_opne_listp =
false;
1908 opno = opclause->
opno;
1911 if (
equal(leftop, partkey))
1913 else if (
equal(rightop, partkey))
1956 &op_strategy, &op_lefttype,
1970 &op_strategy, &op_lefttype,
1973 is_opne_listp =
true;
2042 context->has_exec_param =
true;
2049 context->has_mutable_arg =
true;
2060 context->has_mutable_op =
true;
2103 op_righttype, op_righttype,
2108 elog(
ERROR,
"invalid partition strategy: %c",
2122 partclause->
keyno = partkeyidx;
2126 partclause->
opno = negator;
2132 partclause->
opno = opno;
2136 partclause->
expr = expr;
2137 partclause->
cmpfn = cmpfn;
2147 Oid saop_coll = saop->inputcollid;
2158 if (!
equal(leftop, partkey) ||
2186 &lefttype, &righttype);
2240 context->has_exec_param =
true;
2247 context->has_mutable_arg =
true;
2256 if (
op_volatile(saop_op) != PROVOLATILE_IMMUTABLE)
2258 context->has_mutable_op =
true;
2289 if (arr->constisnull)
2294 &elemlen, &elembyval, &elemalign);
2297 elemlen, elembyval, elemalign,
2298 &elem_values, &elem_nulls,
2300 for (
i = 0;
i < num_elems;
i++)
2317 arr->constcollid, elemlen,
2318 elem_values[
i],
false, elembyval);
2319 elem_exprs =
lappend(elem_exprs, elem_expr);
2331 if (arrexpr->multidims)
2350 foreach(lc1, elem_exprs)
2357 elem_clauses =
lappend(elem_clauses, elem_clause);
2371 else if (*clause_steps ==
NIL)
2406 return boolmatchstatus;
2441 Expr *step_lastexpr,
2447 Assert(step_nullkeys == NULL ||
2499 Expr *step_lastexpr,
2520 if (cur_keyno < final_keyno)
2534 if (pc->
keyno > cur_keyno)
2553 if (pc->
keyno == cur_keyno)
2608 context->rel->part_scheme->partnatts);
2621 step_exprs1 =
lappend(step_exprs1, step_lastexpr);
2626 step_cmpfns1 =
lappend_oid(step_cmpfns1, step_lastcmpfn);
2629 step_opstrategy, step_op_is_ne,
2630 step_exprs1, step_cmpfns1,
2632 result =
lappend(result, step);
2669 int *partindices = boundinfo->
indexes;
2670 int partnatts =
context->partnatts;
2674 int greatest_modulus;
2692 for (
i = 0;
i < partnatts;
i++)
2698 greatest_modulus = boundinfo->
nindexes;
2699 if (partindices[rowHash % greatest_modulus] >= 0)
2750 bool inclusive =
false;
2783 maxoff = boundinfo->
ndatums - 1;
2811 if (off >= 0 && is_equal)
2844 if (off >= 0 && is_equal)
2864 if (!is_equal || !inclusive)
2882 if (off > boundinfo->
ndatums - 1)
2896 if (off >= 0 && is_equal && !inclusive)
2912 elog(
ERROR,
"invalid strategy number %d", opstrategy);
2916 Assert(minoff >= 0 && maxoff >= 0);
2958 int partnatts =
context->partnatts;
2959 int *partindices = boundinfo->
indexes;
2964 bool inclusive =
false;
2967 Assert(nvalues <= partnatts);
2993 if (partindices[minoff] < 0)
2995 if (partindices[maxoff] < 0)
2999 Assert(partindices[minoff] >= 0 &&
3000 partindices[maxoff] >= 0);
3010 if (nvalues < partnatts)
3023 if (off >= 0 && is_equal)
3025 if (nvalues == partnatts)
3033 int saved_off = off;
3054 boundinfo->
datums[off - 1],
3055 boundinfo->
kind[off - 1],
3066 boundinfo->
kind[off],
3077 if (boundinfo->
kind[off][nvalues] ==
3088 while (off < boundinfo->ndatums - 1)
3094 boundinfo->
datums[off + 1],
3095 boundinfo->
kind[off + 1],
3106 boundinfo->
kind[off],
3116 Assert(minoff >= 0 && maxoff >= 0);
3159 if (is_equal && nvalues < partnatts)
3174 while (off >= 1 && off < boundinfo->ndatums - 1)
3179 nextoff = inclusive ? off - 1 : off + 1;
3183 boundinfo->
datums[nextoff],
3184 boundinfo->
kind[nextoff],
3196 boundinfo->
kind[off],
3199 minoff = inclusive ? off : off + 1;
3235 if (is_equal && nvalues < partnatts)
3237 while (off >= 1 && off < boundinfo->ndatums - 1)
3242 nextoff = inclusive ? off + 1 : off - 1;
3245 boundinfo->
datums[nextoff],
3246 boundinfo->
kind[nextoff],
3258 boundinfo->
kind[off],
3261 maxoff = inclusive ? off + 1 : off;
3273 else if (!is_equal || inclusive)
3289 elog(
ERROR,
"invalid strategy number %d", opstrategy);
3293 Assert(minoff >= 0 && minoff <= boundinfo->ndatums);
3294 Assert(maxoff >= 0 && maxoff <= boundinfo->ndatums);
3302 if (minoff < boundinfo->ndatums && partindices[minoff] < 0)
3304 int lastkey = nvalues - 1;
3306 if (boundinfo->
kind[minoff][lastkey] ==
3321 if (maxoff >= 1 && partindices[maxoff] < 0)
3323 int lastkey = nvalues - 1;
3325 if (boundinfo->
kind[maxoff - 1][lastkey] ==
3333 Assert(minoff >= 0 && maxoff >= 0);
3334 if (minoff <= maxoff)
3393 foreach(lc2, step->
exprs)
3399 execparamids =
bms_join(execparamids,
3404 return execparamids;
3440 for (keyno = 0; keyno <
context->partnatts; keyno++)
3490 if (cmpfn !=
context->stepcmpfuncs[stateidx].fn_oid)
3498 if (cmpfn ==
context->partsupfunc[keyno].fn_oid)
3520 partsupfunc = &
context->stepcmpfuncs[stateidx];
3546 elog(
ERROR,
"unexpected partition strategy: %d",
3602 elog(
ERROR,
"invalid pruning combine step argument");
3603 step_result = step_results[step_id];
3604 Assert(step_result != NULL);
3626 elog(
ERROR,
"invalid pruning combine step argument");
3627 step_result = step_results[step_id];
3628 Assert(step_result != NULL);
3674 Expr **outconst,
bool *notclause)
3685 if (!IsBuiltinBooleanOpfamily(partopfamily))
3692 leftop = btest->
arg;
3696 if (
equal(leftop, partkey))
3734 if (
equal(leftop, partkey))
3761 Expr *expr,
int stateidx,
3769 *
value = con->constvalue;
3770 *isnull = con->constisnull;
3788 exprstate =
context->exprstates[stateidx];
AppendRelInfo ** find_appinfos_by_relids(PlannerInfo *root, Relids relids, int *nappinfos)
Node * adjust_appendrel_attrs(PlannerInfo *root, Node *node, int nappinfos, AppendRelInfo **appinfos)
Node * adjust_appendrel_attrs_multilevel(PlannerInfo *root, Node *node, RelOptInfo *childrel, RelOptInfo *parentrel)
#define DatumGetArrayTypeP(X)
void deconstruct_array(ArrayType *array, Oid elmtype, int elmlen, bool elmbyval, char elmalign, Datum **elemsp, bool **nullsp, int *nelemsp)
Bitmapset * bms_join(Bitmapset *a, Bitmapset *b)
bool bms_equal(const Bitmapset *a, const Bitmapset *b)
int bms_next_member(const Bitmapset *a, int prevbit)
int bms_num_members(const Bitmapset *a)
bool bms_is_member(int x, const Bitmapset *a)
Bitmapset * bms_make_singleton(int x)
Bitmapset * bms_add_member(Bitmapset *a, int x)
Bitmapset * bms_add_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_del_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_int_members(Bitmapset *a, const Bitmapset *b)
Bitmapset * bms_del_member(Bitmapset *a, int x)
Bitmapset * bms_copy(const Bitmapset *a)
Bitmapset * bms_add_range(Bitmapset *a, int lower, int upper)
static Datum values[MAXATTR]
#define Assert(condition)
#define OidIsValid(objectId)
bool contain_volatile_functions(Node *clause)
bool enable_partition_pruning
bool equal(const void *a, const void *b)
static Datum ExecEvalExprSwitchContext(ExprState *state, ExprContext *econtext, bool *isNull)
void fmgr_info_cxt(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt)
void fmgr_info_copy(FmgrInfo *dstinfo, FmgrInfo *srcinfo, MemoryContext destcxt)
#define HASHEXTENDED_PROC
List * lappend(List *list, void *datum)
List * lappend_int(List *list, int datum)
List * lappend_oid(List *list, Oid datum)
List * list_copy(const List *oldlist)
void list_free(List *list)
List * list_concat(List *list1, const List *list2)
List * list_concat_copy(const List *list1, const List *list2)
void get_op_opfamily_properties(Oid opno, Oid opfamily, bool ordering_op, int *strategy, Oid *lefttype, Oid *righttype)
void get_typlenbyvalalign(Oid typid, int16 *typlen, bool *typbyval, char *typalign)
Oid get_opfamily_proc(Oid opfamily, Oid lefttype, Oid righttype, int16 procnum)
char op_volatile(Oid opno)
bool op_in_opfamily(Oid opno, Oid opfamily)
Oid get_negator(Oid opno)
Oid get_commutator(Oid opno)
Expr * make_opclause(Oid opno, Oid opresulttype, bool opretset, Expr *leftop, Expr *rightop, Oid opcollid, Oid inputcollid)
Const * makeConst(Oid consttype, int32 consttypmod, Oid constcollid, int constlen, Datum constvalue, bool constisnull, bool constbyval)
Expr * makeBoolExpr(BoolExprType boolop, List *args, int location)
Node * makeBoolConst(bool value, bool isnull)
void pfree(void *pointer)
void * palloc0(Size size)
MemoryContext CurrentMemoryContext
static bool is_andclause(const void *clause)
static Expr * get_notclausearg(const void *notclause)
static bool is_orclause(const void *clause)
static Node * get_rightop(const void *clause)
#define expression_tree_walker(n, w, c)
static bool is_notclause(const void *clause)
static Node * get_leftop(const void *clause)
#define IsA(nodeptr, _type_)
#define castNode(_type_, nodeptr)
@ PARTITION_STRATEGY_HASH
@ PARTITION_STRATEGY_LIST
@ PARTITION_STRATEGY_RANGE
@ PARTITION_RANGE_DATUM_MAXVALUE
@ PARTITION_RANGE_DATUM_MINVALUE
int32 partition_rbound_datum_cmp(FmgrInfo *partsupfunc, Oid *partcollation, Datum *rb_datums, PartitionRangeDatumKind *rb_kind, Datum *tuple_datums, int n_tuple_datums)
uint64 compute_partition_hash_value(int partnatts, FmgrInfo *partsupfunc, const Oid *partcollation, const Datum *values, const bool *isnull)
int partition_range_datum_bsearch(FmgrInfo *partsupfunc, Oid *partcollation, PartitionBoundInfo boundinfo, int nvalues, Datum *values, bool *is_equal)
int partition_list_bsearch(FmgrInfo *partsupfunc, Oid *partcollation, PartitionBoundInfo boundinfo, Datum value, bool *is_equal)
#define partition_bound_has_default(bi)
#define partition_bound_accepts_nulls(bi)
@ PARTCLAUSE_MATCH_CONTRADICT
@ PARTCLAUSE_MATCH_CLAUSE
@ PARTCLAUSE_MATCH_NULLNESS
static List * add_part_relids(List *allpartrelids, Bitmapset *partrelids)
static PartitionPruneStep * gen_prune_step_combine(GeneratePruningStepsContext *context, List *source_stepids, PartitionPruneCombineOp combineOp)
static List * make_partitionedrel_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, List *prunequal, Bitmapset *partrelids, int *relid_subplan_map, Bitmapset **matchedsubplans)
static Bitmapset * get_partkey_exec_paramids(List *steps)
Bitmapset * get_matching_partitions(PartitionPruneContext *context, List *pruning_steps)
struct PruneStepResult PruneStepResult
PartitionPruneInfo * make_partition_pruneinfo(PlannerInfo *root, RelOptInfo *parentrel, List *subpaths, List *prunequal)
static PartClauseMatchStatus match_clause_to_partition_key(GeneratePruningStepsContext *context, Expr *clause, Expr *partkey, int partkeyidx, bool *clause_is_not_null, PartClauseInfo **pc, List **clause_steps)
Bitmapset * prune_append_rel_partitions(RelOptInfo *rel)
static PruneStepResult * get_matching_list_bounds(PartitionPruneContext *context, StrategyNumber opstrategy, Datum value, int nvalues, FmgrInfo *partsupfunc, Bitmapset *nullkeys)
static PartClauseMatchStatus match_boolean_partition_clause(Oid partopfamily, Expr *clause, Expr *partkey, Expr **outconst, bool *notclause)
static PruneStepResult * get_matching_hash_bounds(PartitionPruneContext *context, StrategyNumber opstrategy, Datum *values, int nvalues, FmgrInfo *partsupfunc, Bitmapset *nullkeys)
static List * get_steps_using_prefix(GeneratePruningStepsContext *context, StrategyNumber step_opstrategy, bool step_op_is_ne, Expr *step_lastexpr, Oid step_lastcmpfn, Bitmapset *step_nullkeys, List *prefix)
static List * gen_partprune_steps_internal(GeneratePruningStepsContext *context, List *clauses)
static void gen_partprune_steps(RelOptInfo *rel, List *clauses, PartClauseTarget target, GeneratePruningStepsContext *context)
static void partkey_datum_from_expr(PartitionPruneContext *context, Expr *expr, int stateidx, Datum *value, bool *isnull)
static List * gen_prune_steps_from_opexps(GeneratePruningStepsContext *context, List **keyclauses, Bitmapset *nullkeys)
static PruneStepResult * get_matching_range_bounds(PartitionPruneContext *context, StrategyNumber opstrategy, Datum *values, int nvalues, FmgrInfo *partsupfunc, Bitmapset *nullkeys)
#define PartCollMatchesExprColl(partcoll, exprcoll)
static PruneStepResult * perform_pruning_base_step(PartitionPruneContext *context, PartitionPruneStepOp *opstep)
static PruneStepResult * perform_pruning_combine_step(PartitionPruneContext *context, PartitionPruneStepCombine *cstep, PruneStepResult **step_results)
static List * get_steps_using_prefix_recurse(GeneratePruningStepsContext *context, StrategyNumber step_opstrategy, bool step_op_is_ne, Expr *step_lastexpr, Oid step_lastcmpfn, Bitmapset *step_nullkeys, List *prefix, ListCell *start, List *step_exprs, List *step_cmpfns)
struct GeneratePruningStepsContext GeneratePruningStepsContext
static Bitmapset * pull_exec_paramids(Expr *expr)
static PartitionPruneStep * gen_prune_step_op(GeneratePruningStepsContext *context, StrategyNumber opstrategy, bool op_is_ne, List *exprs, List *cmpfns, Bitmapset *nullkeys)
struct PartClauseInfo PartClauseInfo
static bool pull_exec_paramids_walker(Node *node, Bitmapset **context)
#define PruneCxtStateIdx(partnatts, step_id, keyno)
#define IS_PARTITIONED_REL(rel)
#define planner_rt_fetch(rti, root)
@ RELOPT_OTHER_MEMBER_REL
#define PARTITION_MAX_KEYS
static int list_length(const List *l)
#define list_make1_oid(x1)
#define for_each_cell(cell, lst, initcell)
static ListCell * list_head(const List *l)
static ListCell * lnext(const List *l, const ListCell *c)
#define list_make2(x1, x2)
@ PARTPRUNE_COMBINE_INTERSECT
@ PARTPRUNE_COMBINE_UNION
void check_stack_depth(void)
static bool DatumGetBool(Datum X)
bool predicate_refuted_by(List *predicate_list, List *clause_list, bool weak)
Node * negate_clause(Node *node)
RelOptInfo * find_base_rel(PlannerInfo *root, int relid)
#define HTMaxStrategyNumber
#define BTGreaterStrategyNumber
#define BTMaxStrategyNumber
#define HTEqualStrategyNumber
#define BTLessStrategyNumber
#define BTEqualStrategyNumber
#define BTLessEqualStrategyNumber
#define BTGreaterEqualStrategyNumber
BoolTestType booltesttype
NullTestType nulltesttype
PartitionRangeDatumKind ** kind
Bitmapset * other_subplans
PartitionPruneCombineOp combineOp
StrategyNumber opstrategy
struct FmgrInfo * partsupfunc
Bitmapset * present_parts
List * initial_pruning_steps
List * exec_pruning_steps
Bitmapset * bound_offsets
bool contain_var_clause(Node *node)