@@ -59,8 +59,10 @@ typedef struct
59
59
typedef struct
60
60
{
61
61
const PartRelationInfo * prel ;
62
- Datum least ;
63
- Datum greatest ;
62
+ bool hasLeast ,
63
+ hasGreatest ;
64
+ Datum least ,
65
+ greatest ;
64
66
}WalkerContext ;
65
67
66
68
bool pg_pathman_enable ;
@@ -94,6 +96,9 @@ bool inheritance_disabled;
94
96
95
97
/* Expression tree handlers */
96
98
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 );
97
102
static int make_hash (const PartRelationInfo * prel ,int value );
98
103
static void handle_binary_opexpr (WalkerContext * context ,WrapperNode * result ,const Var * v ,const Const * c );
99
104
static WrapperNode * handle_opexpr (const OpExpr * expr ,WalkerContext * context );
@@ -392,7 +397,10 @@ handle_modification_query(Query *parse)
392
397
393
398
/* Parse syntax tree and extract partition ranges */
394
399
context .prel = prel ;
400
+ context .hasLeast = false;
401
+ context .hasGreatest = false;
395
402
wrap = walk_expr_tree (expr ,& context );
403
+ finish_least_greatest (wrap ,& context );
396
404
ranges = irange_list_intersect (ranges ,wrap -> rangeset );
397
405
398
406
/* 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
457
465
458
466
if (prel != NULL && found )
459
467
{
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 ;
467
476
468
477
if (prel -> parttype == PT_RANGE )
469
478
{
@@ -503,16 +512,18 @@ pathman_set_rel_pathlist_hook(PlannerInfo *root, RelOptInfo *rel, Index rti, Ran
503
512
ranges = list_make1_int (make_irange (0 ,prel -> children_count - 1 , false));
504
513
505
514
/* Make wrappers over restrictions and collect final rangeset */
515
+ context .prel = prel ;
516
+ context .hasLeast = false;
517
+ context .hasGreatest = false;
506
518
wrappers = NIL ;
507
519
foreach (lc ,rel -> baserestrictinfo )
508
520
{
509
521
WrapperNode * wrap ;
510
- WalkerContext context ;
511
-
512
- RestrictInfo * rinfo = (RestrictInfo * )lfirst (lc );
522
+ RestrictInfo * rinfo = (RestrictInfo * )lfirst (lc );
513
523
514
- context .prel = prel ;
515
524
wrap = walk_expr_tree (rinfo -> clause ,& context );
525
+ if (!lc -> next )
526
+ finish_least_greatest (wrap ,& context );
516
527
wrappers = lappend (wrappers ,wrap );
517
528
ranges = irange_list_intersect (ranges ,wrap -> rangeset );
518
529
}
@@ -984,6 +995,74 @@ walk_expr_tree(Expr *expr, WalkerContext *context)
984
995
}
985
996
}
986
997
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
+
987
1066
/*
988
1067
*This function determines which partitions should appear in query plan
989
1068
*/
@@ -1018,7 +1097,33 @@ handle_binary_opexpr(WalkerContext *context, WrapperNode *result,
1018
1097
switch (prel -> parttype )
1019
1098
{
1020
1099
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 )
1022
1127
{
1023
1128
int_value = DatumGetInt32 (c -> constvalue );
1024
1129
key .hash = make_hash (prel ,int_value );
@@ -1309,9 +1414,10 @@ handle_boolexpr(const BoolExpr *expr, WalkerContext *context)
1309
1414
1310
1415
arg = walk_expr_tree ((Expr * )lfirst (lc ),context );
1311
1416
result -> args = lappend (result -> args ,arg );
1312
- switch (expr -> boolop )
1417
+ switch (expr -> boolop )
1313
1418
{
1314
1419
case OR_EXPR :
1420
+ finish_least_greatest (arg ,context );
1315
1421
result -> rangeset = irange_list_union (result -> rangeset ,arg -> rangeset );
1316
1422
break ;
1317
1423
case AND_EXPR :