@@ -170,14 +170,21 @@ static int32 partition_rbound_cmp(PartitionKey key,
170170 bool lower1 , PartitionRangeBound * b2 );
171171static int32 partition_rbound_datum_cmp (PartitionKey key ,
172172 Datum * rb_datums , PartitionRangeDatumKind * rb_kind ,
173- Datum * tuple_datums );
173+ Datum * tuple_datums , int n_tuple_datums );
174174
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 ,
179179 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+
181188static int get_partition_bound_num_indexes (PartitionBoundInfo b );
182189static int get_greatest_modulus (PartitionBoundInfo b );
183190static uint64 compute_hash_value (PartitionKey key , Datum * values , bool * isnull );
@@ -981,8 +988,7 @@ check_new_partition_bound(char *relname, Relation parent,
981988 int greatest_modulus ;
982989 int remainder ;
983990 int offset ;
984- bool equal ,
985- valid_modulus = true;
991+ bool valid_modulus = true;
986992 int prev_modulus , /* Previous largest modulus */
987993 next_modulus ; /* Next largest modulus */
988994
@@ -995,12 +1001,13 @@ check_new_partition_bound(char *relname, Relation parent,
9951001 * modulus 10 and a partition with modulus 15, because 10
9961002 * is not a factor of 15.
9971003 *
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 .
10011007 */
1002- offset = partition_bound_bsearch (key , boundinfo , spec ,
1003- true, & equal );
1008+ offset = partition_hash_bsearch (key , boundinfo ,
1009+ spec -> modulus ,
1010+ spec -> remainder );
10041011 if (offset < 0 )
10051012 {
10061013 next_modulus = DatumGetInt32 (datums [0 ][0 ]);
@@ -1074,9 +1081,9 @@ check_new_partition_bound(char *relname, Relation parent,
10741081 int offset ;
10751082 bool equal ;
10761083
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 );
10801087 if (offset >= 0 && equal )
10811088 {
10821089 overlap = true;
@@ -1148,8 +1155,8 @@ check_new_partition_bound(char *relname, Relation parent,
11481155 * since the index array is initialised with an extra -1
11491156 * at the end.
11501157 */
1151- offset = partition_bound_bsearch (key , boundinfo , lower ,
1152- true, & equal );
1158+ offset = partition_range_bsearch (key , boundinfo , lower ,
1159+ & equal );
11531160
11541161 if (boundinfo -> indexes [offset + 1 ] < 0 )
11551162 {
@@ -1162,10 +1169,16 @@ check_new_partition_bound(char *relname, Relation parent,
11621169 if (offset + 1 < boundinfo -> ndatums )
11631170 {
11641171 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 );
11651179
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 );
11691182 if (cmpval < 0 )
11701183 {
11711184 /*
@@ -2574,11 +2587,9 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull)
25742587 {
25752588 bool equal = false;
25762589
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 );
25822593 if (bound_offset >= 0 && equal )
25832594 part_index = partdesc -> boundinfo -> indexes [bound_offset ];
25842595 }
@@ -2605,12 +2616,11 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull)
26052616
26062617 if (!range_partkey_has_null )
26072618 {
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 );
26142624 /*
26152625 * The bound at bound_offset is less than or equal to the
26162626 * tuple value, so the bound at offset+1 is the upper
@@ -2881,12 +2891,12 @@ partition_rbound_cmp(PartitionKey key,
28812891static int32
28822892partition_rbound_datum_cmp (PartitionKey key ,
28832893 Datum * rb_datums , PartitionRangeDatumKind * rb_kind ,
2884- Datum * tuple_datums )
2894+ Datum * tuple_datums , int n_tuple_datums )
28852895{
28862896 int i ;
28872897 int32 cmpval = -1 ;
28882898
2889- for (i = 0 ; i < key -> partnatts ; i ++ )
2899+ for (i = 0 ; i < n_tuple_datums ; i ++ )
28902900 {
28912901 if (rb_kind [i ] == PARTITION_RANGE_DATUM_MINVALUE )
28922902 return -1 ;
@@ -2905,84 +2915,104 @@ partition_rbound_datum_cmp(PartitionKey key,
29052915}
29062916
29072917/*
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
29092921 *
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 .
29122924 */
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 )
29162929{
2917- Datum * bound_datums = boundinfo -> datums [offset ];
2918- int32 cmpval = -1 ;
2930+ int lo ,
2931+ hi ,
2932+ mid ;
29192933
2920- switch (key -> strategy )
2934+ lo = -1 ;
2935+ hi = boundinfo -> ndatums - 1 ;
2936+ while (lo < hi )
29212937 {
2922- case PARTITION_STRATEGY_HASH :
2923- {
2924- PartitionBoundSpec * spec = (PartitionBoundSpec * ) probe ;
2938+ int32 cmpval ;
29252939
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 )
29292950 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+ }
29372955
2938- case PARTITION_STRATEGY_RANGE :
2939- {
2940- PartitionRangeDatumKind * kind = boundinfo -> kind [offset ];
2956+ return lo ;
2957+ }
29412958
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 ;
29502976
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 ;
29612982
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 ;
29652999 }
29663000
2967- return cmpval ;
3001+ return lo ;
29683002}
29693003
29703004/*
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
29793008 *
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 .
29823011 */
29833012static 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 )
29863016{
29873017 int lo ,
29883018 hi ,
@@ -2995,8 +3025,11 @@ partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo,
29953025 int32 cmpval ;
29963026
29973027 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 );
30003033 if (cmpval <= 0 )
30013034 {
30023035 lo = mid ;
@@ -3012,6 +3045,48 @@ partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo,
30123045 return lo ;
30133046}
30143047
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+
30153090/*
30163091 * get_default_oid_from_partdesc
30173092 *
0 commit comments