@@ -170,14 +170,21 @@ static int32 partition_rbound_cmp(PartitionKey key,
170
170
bool lower1 , PartitionRangeBound * b2 );
171
171
static int32 partition_rbound_datum_cmp (PartitionKey key ,
172
172
Datum * rb_datums , PartitionRangeDatumKind * rb_kind ,
173
- Datum * tuple_datums );
173
+ Datum * tuple_datums , int n_tuple_datums );
174
174
175
- static int32 partition_bound_cmp (PartitionKey key ,
176
- PartitionBoundInfo boundinfo ,
177
- int offset , void * probe , bool probe_is_bound );
178
- static int partition_bound_bsearch (PartitionKey key ,
175
+ static int partition_list_bsearch (PartitionKey key ,
176
+ PartitionBoundInfo boundinfo ,
177
+ Datum value , bool * is_equal );
178
+ static int partition_range_bsearch (PartitionKey key ,
179
179
PartitionBoundInfo boundinfo ,
180
- void * probe , bool probe_is_bound , bool * is_equal );
180
+ PartitionRangeBound * probe , bool * is_equal );
181
+ static int partition_range_datum_bsearch (PartitionKey key ,
182
+ PartitionBoundInfo boundinfo ,
183
+ int nvalues , Datum * values , bool * is_equal );
184
+ static int partition_hash_bsearch (PartitionKey key ,
185
+ PartitionBoundInfo boundinfo ,
186
+ int modulus , int remainder );
187
+
181
188
static int get_partition_bound_num_indexes (PartitionBoundInfo b );
182
189
static int get_greatest_modulus (PartitionBoundInfo b );
183
190
static uint64 compute_hash_value (PartitionKey key , Datum * values , bool * isnull );
@@ -981,8 +988,7 @@ check_new_partition_bound(char *relname, Relation parent,
981
988
int greatest_modulus ;
982
989
int remainder ;
983
990
int offset ;
984
- bool equal ,
985
- valid_modulus = true;
991
+ bool valid_modulus = true;
986
992
int prev_modulus , /* Previous largest modulus */
987
993
next_modulus ; /* Next largest modulus */
988
994
@@ -995,12 +1001,13 @@ check_new_partition_bound(char *relname, Relation parent,
995
1001
* modulus 10 and a partition with modulus 15, because 10
996
1002
* is not a factor of 15.
997
1003
*
998
- * Get greatest bound in array boundinfo->datums which is
999
- * less than or equal to spec->modulus and
1000
- * spec->remainder.
1004
+ * Get the greatest (modulus, remainder) pair contained in
1005
+ * boundinfo->datums that is less than or equal to the
1006
+ * ( spec->modulus, spec-> remainder) pair .
1001
1007
*/
1002
- offset = partition_bound_bsearch (key , boundinfo , spec ,
1003
- true, & equal );
1008
+ offset = partition_hash_bsearch (key , boundinfo ,
1009
+ spec -> modulus ,
1010
+ spec -> remainder );
1004
1011
if (offset < 0 )
1005
1012
{
1006
1013
next_modulus = DatumGetInt32 (datums [0 ][0 ]);
@@ -1074,9 +1081,9 @@ check_new_partition_bound(char *relname, Relation parent,
1074
1081
int offset ;
1075
1082
bool equal ;
1076
1083
1077
- offset = partition_bound_bsearch (key , boundinfo ,
1078
- & val -> constvalue ,
1079
- true, & equal );
1084
+ offset = partition_list_bsearch (key , boundinfo ,
1085
+ val -> constvalue ,
1086
+ & equal );
1080
1087
if (offset >= 0 && equal )
1081
1088
{
1082
1089
overlap = true;
@@ -1148,8 +1155,8 @@ check_new_partition_bound(char *relname, Relation parent,
1148
1155
* since the index array is initialised with an extra -1
1149
1156
* at the end.
1150
1157
*/
1151
- offset = partition_bound_bsearch (key , boundinfo , lower ,
1152
- true, & equal );
1158
+ offset = partition_range_bsearch (key , boundinfo , lower ,
1159
+ & equal );
1153
1160
1154
1161
if (boundinfo -> indexes [offset + 1 ] < 0 )
1155
1162
{
@@ -1162,10 +1169,16 @@ check_new_partition_bound(char *relname, Relation parent,
1162
1169
if (offset + 1 < boundinfo -> ndatums )
1163
1170
{
1164
1171
int32 cmpval ;
1172
+ Datum * datums ;
1173
+ PartitionRangeDatumKind * kind ;
1174
+ bool is_lower ;
1175
+
1176
+ datums = boundinfo -> datums [offset + 1 ];
1177
+ kind = boundinfo -> kind [offset + 1 ];
1178
+ is_lower = (boundinfo -> indexes [offset + 1 ] == -1 );
1165
1179
1166
- cmpval = partition_bound_cmp (key , boundinfo ,
1167
- offset + 1 , upper ,
1168
- true);
1180
+ cmpval = partition_rbound_cmp (key , datums , kind ,
1181
+ is_lower , upper );
1169
1182
if (cmpval < 0 )
1170
1183
{
1171
1184
/*
@@ -2574,11 +2587,9 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull)
2574
2587
{
2575
2588
bool equal = false;
2576
2589
2577
- bound_offset = partition_bound_bsearch (key ,
2578
- partdesc -> boundinfo ,
2579
- values ,
2580
- false,
2581
- & equal );
2590
+ bound_offset = partition_list_bsearch (key ,
2591
+ partdesc -> boundinfo ,
2592
+ values [0 ], & equal );
2582
2593
if (bound_offset >= 0 && equal )
2583
2594
part_index = partdesc -> boundinfo -> indexes [bound_offset ];
2584
2595
}
@@ -2605,12 +2616,11 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull)
2605
2616
2606
2617
if (!range_partkey_has_null )
2607
2618
{
2608
- bound_offset = partition_bound_bsearch (key ,
2609
- partdesc -> boundinfo ,
2610
- values ,
2611
- false,
2612
- & equal );
2613
-
2619
+ bound_offset = partition_range_datum_bsearch (key ,
2620
+ partdesc -> boundinfo ,
2621
+ key -> partnatts ,
2622
+ values ,
2623
+ & equal );
2614
2624
/*
2615
2625
* The bound at bound_offset is less than or equal to the
2616
2626
* tuple value, so the bound at offset+1 is the upper
@@ -2881,12 +2891,12 @@ partition_rbound_cmp(PartitionKey key,
2881
2891
static int32
2882
2892
partition_rbound_datum_cmp (PartitionKey key ,
2883
2893
Datum * rb_datums , PartitionRangeDatumKind * rb_kind ,
2884
- Datum * tuple_datums )
2894
+ Datum * tuple_datums , int n_tuple_datums )
2885
2895
{
2886
2896
int i ;
2887
2897
int32 cmpval = -1 ;
2888
2898
2889
- for (i = 0 ; i < key -> partnatts ; i ++ )
2899
+ for (i = 0 ; i < n_tuple_datums ; i ++ )
2890
2900
{
2891
2901
if (rb_kind [i ] == PARTITION_RANGE_DATUM_MINVALUE )
2892
2902
return -1 ;
@@ -2905,84 +2915,104 @@ partition_rbound_datum_cmp(PartitionKey key,
2905
2915
}
2906
2916
2907
2917
/*
2908
- * partition_bound_cmp
2918
+ * partition_list_bsearch
2919
+ * Returns the index of the greatest bound datum that is less than equal
2920
+ * to the given value or -1 if all of the bound datums are greater
2909
2921
*
2910
- * Return whether the bound at offset in boundinfo is <, =, or > the argument
2911
- * specified in *probe .
2922
+ * *is_equal is set to true if the bound datum at the returned index is equal
2923
+ * to the input value .
2912
2924
*/
2913
- static int32
2914
- partition_bound_cmp (PartitionKey key , PartitionBoundInfo boundinfo ,
2915
- int offset , void * probe , bool probe_is_bound )
2925
+ static int
2926
+ partition_list_bsearch (PartitionKey key ,
2927
+ PartitionBoundInfo boundinfo ,
2928
+ Datum value , bool * is_equal )
2916
2929
{
2917
- Datum * bound_datums = boundinfo -> datums [offset ];
2918
- int32 cmpval = -1 ;
2930
+ int lo ,
2931
+ hi ,
2932
+ mid ;
2919
2933
2920
- switch (key -> strategy )
2934
+ lo = -1 ;
2935
+ hi = boundinfo -> ndatums - 1 ;
2936
+ while (lo < hi )
2921
2937
{
2922
- case PARTITION_STRATEGY_HASH :
2923
- {
2924
- PartitionBoundSpec * spec = (PartitionBoundSpec * ) probe ;
2938
+ int32 cmpval ;
2925
2939
2926
- cmpval = partition_hbound_cmp (DatumGetInt32 (bound_datums [0 ]),
2927
- DatumGetInt32 (bound_datums [1 ]),
2928
- spec -> modulus , spec -> remainder );
2940
+ mid = (lo + hi + 1 ) / 2 ;
2941
+ cmpval = DatumGetInt32 (FunctionCall2Coll (& key -> partsupfunc [0 ],
2942
+ key -> partcollation [0 ],
2943
+ boundinfo -> datums [mid ][0 ],
2944
+ value ));
2945
+ if (cmpval <= 0 )
2946
+ {
2947
+ lo = mid ;
2948
+ * is_equal = (cmpval == 0 );
2949
+ if (* is_equal )
2929
2950
break ;
2930
- }
2931
- case PARTITION_STRATEGY_LIST :
2932
- cmpval = DatumGetInt32 (FunctionCall2Coll (& key -> partsupfunc [0 ],
2933
- key -> partcollation [0 ],
2934
- bound_datums [0 ],
2935
- * (Datum * ) probe ));
2936
- break ;
2951
+ }
2952
+ else
2953
+ hi = mid - 1 ;
2954
+ }
2937
2955
2938
- case PARTITION_STRATEGY_RANGE :
2939
- {
2940
- PartitionRangeDatumKind * kind = boundinfo -> kind [offset ];
2956
+ return lo ;
2957
+ }
2941
2958
2942
- if (probe_is_bound )
2943
- {
2944
- /*
2945
- * We need to pass whether the existing bound is a lower
2946
- * bound, so that two equal-valued lower and upper bounds
2947
- * are not regarded equal.
2948
- */
2949
- bool lower = boundinfo -> indexes [offset ] < 0 ;
2959
+ /*
2960
+ * partition_range_bsearch
2961
+ * Returns the index of the greatest range bound that is less than or
2962
+ * equal to the given range bound or -1 if all of the range bounds are
2963
+ * greater
2964
+ *
2965
+ * *is_equal is set to true if the range bound at the returned index is equal
2966
+ * to the input range bound
2967
+ */
2968
+ static int
2969
+ partition_range_bsearch (PartitionKey key ,
2970
+ PartitionBoundInfo boundinfo ,
2971
+ PartitionRangeBound * probe , bool * is_equal )
2972
+ {
2973
+ int lo ,
2974
+ hi ,
2975
+ mid ;
2950
2976
2951
- cmpval = partition_rbound_cmp (key ,
2952
- bound_datums , kind , lower ,
2953
- (PartitionRangeBound * ) probe );
2954
- }
2955
- else
2956
- cmpval = partition_rbound_datum_cmp (key ,
2957
- bound_datums , kind ,
2958
- (Datum * ) probe );
2959
- break ;
2960
- }
2977
+ lo = -1 ;
2978
+ hi = boundinfo -> ndatums - 1 ;
2979
+ while (lo < hi )
2980
+ {
2981
+ int32 cmpval ;
2961
2982
2962
- default :
2963
- elog (ERROR , "unexpected partition strategy: %d" ,
2964
- (int ) key -> strategy );
2983
+ mid = (lo + hi + 1 ) / 2 ;
2984
+ cmpval = partition_rbound_cmp (key ,
2985
+ boundinfo -> datums [mid ],
2986
+ boundinfo -> kind [mid ],
2987
+ (boundinfo -> indexes [mid ] == -1 ),
2988
+ probe );
2989
+ if (cmpval <= 0 )
2990
+ {
2991
+ lo = mid ;
2992
+ * is_equal = (cmpval == 0 );
2993
+
2994
+ if (* is_equal )
2995
+ break ;
2996
+ }
2997
+ else
2998
+ hi = mid - 1 ;
2965
2999
}
2966
3000
2967
- return cmpval ;
3001
+ return lo ;
2968
3002
}
2969
3003
2970
3004
/*
2971
- * Binary search on a collection of partition bounds. Returns greatest
2972
- * bound in array boundinfo->datums which is less than or equal to *probe.
2973
- * If all bounds in the array are greater than *probe, -1 is returned.
2974
- *
2975
- * *probe could either be a partition bound or a Datum array representing
2976
- * the partition key of a tuple being routed; probe_is_bound tells which.
2977
- * We pass that down to the comparison function so that it can interpret the
2978
- * contents of *probe accordingly.
3005
+ * partition_range_bsearch
3006
+ * Returns the index of the greatest range bound that is less than or
3007
+ * equal to the given tuple or -1 if all of the range bounds are greater
2979
3008
*
2980
- * *is_equal is set to whether the bound at the returned index is equal with
2981
- * *probe .
3009
+ * *is_equal is set to true if the range bound at the returned index is equal
3010
+ * to the input tuple .
2982
3011
*/
2983
3012
static int
2984
- partition_bound_bsearch (PartitionKey key , PartitionBoundInfo boundinfo ,
2985
- void * probe , bool probe_is_bound , bool * is_equal )
3013
+ partition_range_datum_bsearch (PartitionKey key ,
3014
+ PartitionBoundInfo boundinfo ,
3015
+ int nvalues , Datum * values , bool * is_equal )
2986
3016
{
2987
3017
int lo ,
2988
3018
hi ,
@@ -2995,8 +3025,11 @@ partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo,
2995
3025
int32 cmpval ;
2996
3026
2997
3027
mid = (lo + hi + 1 ) / 2 ;
2998
- cmpval = partition_bound_cmp (key , boundinfo , mid , probe ,
2999
- probe_is_bound );
3028
+ cmpval = partition_rbound_datum_cmp (key ,
3029
+ boundinfo -> datums [mid ],
3030
+ boundinfo -> kind [mid ],
3031
+ values ,
3032
+ nvalues );
3000
3033
if (cmpval <= 0 )
3001
3034
{
3002
3035
lo = mid ;
@@ -3012,6 +3045,48 @@ partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo,
3012
3045
return lo ;
3013
3046
}
3014
3047
3048
+ /*
3049
+ * partition_hash_bsearch
3050
+ * Returns the index of the greatest (modulus, remainder) pair that is
3051
+ * less than or equal to the given (modulus, remainder) pair or -1 if
3052
+ * all of them are greater
3053
+ */
3054
+ static int
3055
+ partition_hash_bsearch (PartitionKey key ,
3056
+ PartitionBoundInfo boundinfo ,
3057
+ int modulus , int remainder )
3058
+ {
3059
+ int lo ,
3060
+ hi ,
3061
+ mid ;
3062
+
3063
+ lo = -1 ;
3064
+ hi = boundinfo -> ndatums - 1 ;
3065
+ while (lo < hi )
3066
+ {
3067
+ int32 cmpval ,
3068
+ bound_modulus ,
3069
+ bound_remainder ;
3070
+
3071
+ mid = (lo + hi + 1 ) / 2 ;
3072
+ bound_modulus = DatumGetInt32 (boundinfo -> datums [mid ][0 ]);
3073
+ bound_remainder = DatumGetInt32 (boundinfo -> datums [mid ][1 ]);
3074
+ cmpval = partition_hbound_cmp (bound_modulus , bound_remainder ,
3075
+ modulus , remainder );
3076
+ if (cmpval <= 0 )
3077
+ {
3078
+ lo = mid ;
3079
+
3080
+ if (cmpval == 0 )
3081
+ break ;
3082
+ }
3083
+ else
3084
+ hi = mid - 1 ;
3085
+ }
3086
+
3087
+ return lo ;
3088
+ }
3089
+
3015
3090
/*
3016
3091
* get_default_oid_from_partdesc
3017
3092
*
0 commit comments