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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy