Skip to content

Commit 773fbb1

Browse files
author
Alexander Korotkov
committed
BETWEEN support for hash partitioning.
1 parent bb060d7 commit 773fbb1

File tree

1 file changed

+121
-15
lines changed

1 file changed

+121
-15
lines changed

pg_pathman.c

Lines changed: 121 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,10 @@ typedef struct
5959
typedef struct
6060
{
6161
const PartRelationInfo *prel;
62-
Datum least;
63-
Datum greatest;
62+
bool hasLeast,
63+
hasGreatest;
64+
Datum least,
65+
greatest;
6466
} WalkerContext;
6567

6668
bool pg_pathman_enable;
@@ -94,6 +96,9 @@ bool inheritance_disabled;
9496

9597
/* Expression tree handlers */
9698
static WrapperNode *walk_expr_tree(Expr *expr, WalkerContext *context);
99+
static void finish_least_greatest(WrapperNode *wrap, WalkerContext *context);
100+
static Datum increase_hashable_value(const PartRelationInfo *prel, Datum value);
101+
static Datum decrease_hashable_value(const PartRelationInfo *prel, Datum value);
97102
static int make_hash(const PartRelationInfo *prel, int value);
98103
static void handle_binary_opexpr(WalkerContext *context, WrapperNode *result, const Var *v, const Const *c);
99104
static WrapperNode *handle_opexpr(const OpExpr *expr, WalkerContext *context);
@@ -392,7 +397,10 @@ handle_modification_query(Query *parse)
392397

393398
/* Parse syntax tree and extract partition ranges */
394399
context.prel = prel;
400+
context.hasLeast = false;
401+
context.hasGreatest = false;
395402
wrap = walk_expr_tree(expr, &context);
403+
finish_least_greatest(wrap, &context);
396404
ranges = irange_list_intersect(ranges, wrap->rangeset);
397405

398406
/* If only one partition is affected then substitute parent table with partition */
@@ -457,13 +465,14 @@ pathman_set_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, Ran
457465

458466
if (prel != NULL && found)
459467
{
460-
ListCell *lc;
461-
int i;
462-
Oid *dsm_arr;
463-
List *ranges,
464-
*wrappers;
465-
PathKey *pathkeyAsc = NULL,
466-
*pathkeyDesc = NULL;
468+
ListCell *lc;
469+
int i;
470+
Oid *dsm_arr;
471+
List *ranges,
472+
*wrappers;
473+
PathKey *pathkeyAsc = NULL,
474+
*pathkeyDesc = NULL;
475+
WalkerContext context;
467476

468477
if (prel->parttype == PT_RANGE)
469478
{
@@ -503,16 +512,18 @@ pathman_set_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, Ran
503512
ranges = list_make1_int(make_irange(0, prel->children_count - 1, false));
504513

505514
/* Make wrappers over restrictions and collect final rangeset */
515+
context.prel = prel;
516+
context.hasLeast = false;
517+
context.hasGreatest = false;
506518
wrappers = NIL;
507519
foreach(lc, rel->baserestrictinfo)
508520
{
509521
WrapperNode *wrap;
510-
WalkerContext context;
511-
512-
RestrictInfo *rinfo = (RestrictInfo*) lfirst(lc);
522+
RestrictInfo *rinfo = (RestrictInfo*) lfirst(lc);
513523

514-
context.prel = prel;
515524
wrap = walk_expr_tree(rinfo->clause, &context);
525+
if (!lc->next)
526+
finish_least_greatest(wrap, &context);
516527
wrappers = lappend(wrappers, wrap);
517528
ranges = irange_list_intersect(ranges, wrap->rangeset);
518529
}
@@ -984,6 +995,74 @@ walk_expr_tree(Expr *expr, WalkerContext *context)
984995
}
985996
}
986997

998+
static void
999+
finish_least_greatest(WrapperNode *wrap, WalkerContext *context)
1000+
{
1001+
if (context->hasLeast && context->hasGreatest)
1002+
{
1003+
switch (context->prel->atttype)
1004+
{
1005+
case INT4OID:
1006+
{
1007+
int least = DatumGetInt32(context->least),
1008+
greatest = DatumGetInt32(context->greatest);
1009+
List *rangeset = NIL;
1010+
1011+
if (greatest - least + 1 < context->prel->children_count)
1012+
{
1013+
int value,
1014+
hash;
1015+
for (value = least; value <= greatest; value++)
1016+
{
1017+
hash = make_hash(context->prel, value);
1018+
rangeset = irange_list_union(rangeset,
1019+
list_make1_irange(make_irange(hash, hash, true)));
1020+
}
1021+
}
1022+
wrap->rangeset = irange_list_intersect(wrap->rangeset,
1023+
rangeset);
1024+
}
1025+
break;
1026+
default:
1027+
elog(ERROR, "Invalid datatype: %u", context->prel->atttype);
1028+
}
1029+
}
1030+
context->hasLeast = false;
1031+
context->hasGreatest = false;
1032+
}
1033+
1034+
/*
1035+
* Increase value of hash partitioned column.
1036+
*/
1037+
static Datum
1038+
increase_hashable_value(const PartRelationInfo *prel, Datum value)
1039+
{
1040+
switch (prel->atttype)
1041+
{
1042+
case INT4OID:
1043+
return Int32GetDatum(DatumGetInt32(value) + 1);
1044+
default:
1045+
elog(ERROR, "Invalid datatype: %u", prel->atttype);
1046+
return (Datum)0;
1047+
}
1048+
}
1049+
1050+
/*
1051+
* Decrease value of hash partitioned column.
1052+
*/
1053+
static Datum
1054+
decrease_hashable_value(const PartRelationInfo *prel, Datum value)
1055+
{
1056+
switch (prel->atttype)
1057+
{
1058+
case INT4OID:
1059+
return Int32GetDatum(DatumGetInt32(value) - 1);
1060+
default:
1061+
elog(ERROR, "Invalid datatype: %u", prel->atttype);
1062+
return (Datum)0;
1063+
}
1064+
}
1065+
9871066
/*
9881067
* This function determines which partitions should appear in query plan
9891068
*/
@@ -1018,7 +1097,33 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
10181097
switch (prel->parttype)
10191098
{
10201099
case PT_HASH:
1021-
if (strategy == BTEqualStrategyNumber)
1100+
if (strategy == BTLessStrategyNumber ||
1101+
strategy == BTLessEqualStrategyNumber)
1102+
{
1103+
Datum value = c->constvalue;
1104+
1105+
if (strategy == BTLessStrategyNumber)
1106+
value = decrease_hashable_value(prel, value);
1107+
if (!context->hasGreatest || DatumGetInt32(FunctionCall2(&cmp_func, value, context->greatest)) < 0)
1108+
{
1109+
context->greatest = value;
1110+
context->hasGreatest = true;
1111+
}
1112+
}
1113+
else if (strategy == BTGreaterStrategyNumber ||
1114+
strategy == BTGreaterEqualStrategyNumber)
1115+
{
1116+
Datum value = c->constvalue;
1117+
1118+
if (strategy == BTGreaterStrategyNumber)
1119+
value = increase_hashable_value(prel, value);
1120+
if (!context->hasLeast || DatumGetInt32(FunctionCall2(&cmp_func, value, context->least)) > 0)
1121+
{
1122+
context->least = value;
1123+
context->hasLeast = true;
1124+
}
1125+
}
1126+
else if (strategy == BTEqualStrategyNumber)
10221127
{
10231128
int_value = DatumGetInt32(c->constvalue);
10241129
key.hash = make_hash(prel, int_value);
@@ -1309,9 +1414,10 @@ handle_boolexpr(const BoolExpr *expr, WalkerContext *context)
13091414

13101415
arg = walk_expr_tree((Expr *)lfirst(lc), context);
13111416
result->args = lappend(result->args, arg);
1312-
switch(expr->boolop)
1417+
switch (expr->boolop)
13131418
{
13141419
case OR_EXPR:
1420+
finish_least_greatest(arg, context);
13151421
result->rangeset = irange_list_union(result->rangeset, arg->rangeset);
13161422
break;
13171423
case AND_EXPR:

0 commit comments

Comments
 (0)