@@ -170,14 +170,21 @@ static int32 partition_rbound_cmp(PartitionKey key,
170170bool lower1 ,PartitionRangeBound * b2 );
171171static int32 partition_rbound_datum_cmp (PartitionKey key ,
172172Datum * 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 ,
179179PartitionBoundInfo 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,
981988int greatest_modulus ;
982989int remainder ;
983990int offset ;
984- bool equal ,
985- valid_modulus = true;
991+ bool valid_modulus = true;
986992int prev_modulus ,/* Previous largest modulus */
987993next_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 greatestbound in array boundinfo->datums which is
999- * less than or equal tospec->modulus and
1000- * spec->remainder.
1004+ * Getthe greatest(modulus, remainder) pair contained in
1005+ *boundinfo->datums that is less than or equal tothe
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 );
10041011if (offset < 0 )
10051012{
10061013next_modulus = DatumGetInt32 (datums [0 ][0 ]);
@@ -1074,9 +1081,9 @@ check_new_partition_bound(char *relname, Relation parent,
10741081int offset ;
10751082bool 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 );
10801087if (offset >=0 && equal )
10811088{
10821089overlap = 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
11541161if (boundinfo -> indexes [offset + 1 ]< 0 )
11551162{
@@ -1162,10 +1169,16 @@ check_new_partition_bound(char *relname, Relation parent,
11621169if (offset + 1 < boundinfo -> ndatums )
11631170{
11641171int32 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 );
11691182if (cmpval < 0 )
11701183{
11711184/*
@@ -2574,11 +2587,9 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull)
25742587{
25752588bool 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 );
25822593if (bound_offset >=0 && equal )
25832594part_index = partdesc -> boundinfo -> indexes [bound_offset ];
25842595}
@@ -2605,12 +2616,11 @@ get_partition_for_tuple(Relation relation, Datum *values, bool *isnull)
26052616
26062617if (!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 ,
28832893Datum * rb_datums ,PartitionRangeDatumKind * rb_kind ,
2884- Datum * tuple_datums )
2894+ Datum * tuple_datums , int n_tuple_datums )
28852895{
28862896int i ;
28872897int32 cmpval = -1 ;
28882898
2889- for (i = 0 ;i < key -> partnatts ;i ++ )
2899+ for (i = 0 ;i < n_tuple_datums ;i ++ )
28902900{
28912901if (rb_kind [i ]== PARTITION_RANGE_DATUM_MINVALUE )
28922902return -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 )
29292950break ;
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 towhether the bound at the returned index is equal with
2981- **probe .
3009+ * *is_equal is set totrue if therange 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{
29873017int lo ,
29883018hi ,
@@ -2995,8 +3025,11 @@ partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo,
29953025int32 cmpval ;
29963026
29973027mid = (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 );
30003033if (cmpval <=0 )
30013034{
30023035lo = mid ;
@@ -3012,6 +3045,48 @@ partition_bound_bsearch(PartitionKey key, PartitionBoundInfo boundinfo,
30123045return 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 *