@@ -142,19 +142,23 @@ typedef struct MinMaxMultiOptions
142
142
* The Ranges struct stores the boundary values in a single array, but we
143
143
* treat regular and single-point ranges differently to save space. For
144
144
* regular ranges (with different boundary values) we have to store both
145
- * values, while for "single-point ranges" we only need to save one value.
145
+ * the lower and upper bound of the range, while for "single-point ranges"
146
+ * we only need to store a single value.
146
147
*
147
148
* The 'values' array stores boundary values for regular ranges first (there
148
149
* are 2*nranges values to store), and then the nvalues boundary values for
149
150
* single-point ranges. That is, we have (2*nranges + nvalues) boundary
150
151
* values in the array.
151
152
*
152
- * +---------------------------------+ -------------------------------+
153
- * | ranges (sorted pairs of values ) | sorted values (single points ) |
154
- * +---------------------------------+ -------------------------------+
153
+ * +-------------------------+ ----------------------------------+
154
+ * | ranges (2 * nranges of ) | single point values (nvalues of ) |
155
+ * +-------------------------+ ----------------------------------+
155
156
*
156
157
* This allows us to quickly add new values, and store outliers without
157
- * making the other ranges very wide.
158
+ * having to widen any of the existing range values.
159
+ *
160
+ * 'nsorted' denotes how many of 'nvalues' in the values[] array are sorted.
161
+ * When nsorted == nvalues, all single point values are sorted.
158
162
*
159
163
* We never store more than maxvalues values (as set by values_per_range
160
164
* reloption). If needed we merge some of the ranges.
@@ -173,10 +177,10 @@ typedef struct Ranges
173
177
FmgrInfo * cmp ;
174
178
175
179
/* (2*nranges + nvalues) <= maxvalues */
176
- int nranges ; /* number of ranges in the array (stored) */
177
- int nsorted ; /* number of sorted values (ranges + points) */
178
- int nvalues ; /* number of values in the data array (all) */
179
- int maxvalues ; /* maximum number of values (reloption) */
180
+ int nranges ; /* number of ranges in the values[] array */
181
+ int nsorted ; /* number of nvalues which are sorted */
182
+ int nvalues ; /* number of point values in values[] array */
183
+ int maxvalues ; /* number of elements in the values[] array */
180
184
181
185
/*
182
186
* We simply add the values into a large buffer, without any expensive
@@ -318,102 +322,99 @@ AssertCheckRanges(Ranges *ranges, FmgrInfo *cmpFn, Oid colloid)
318
322
* Check that none of the values are not covered by ranges (both sorted
319
323
* and unsorted)
320
324
*/
321
- for ( i = 0 ; i < ranges -> nvalues ; i ++ )
325
+ if ( ranges -> nranges > 0 )
322
326
{
323
- Datum compar ;
324
- int start ,
325
- end ;
326
- Datum minvalue ,
327
- maxvalue ;
328
-
329
- Datum value = ranges -> values [2 * ranges -> nranges + i ];
330
-
331
- if (ranges -> nranges == 0 )
332
- break ;
333
-
334
- minvalue = ranges -> values [0 ];
335
- maxvalue = ranges -> values [2 * ranges -> nranges - 1 ];
336
-
337
- /*
338
- * Is the value smaller than the minval? If yes, we'll recurse to the
339
- * left side of range array.
340
- */
341
- compar = FunctionCall2Coll (cmpFn , colloid , value , minvalue );
342
-
343
- /* smaller than the smallest value in the first range */
344
- if (DatumGetBool (compar ))
345
- continue ;
346
-
347
- /*
348
- * Is the value greater than the maxval? If yes, we'll recurse to the
349
- * right side of range array.
350
- */
351
- compar = FunctionCall2Coll (cmpFn , colloid , maxvalue , value );
352
-
353
- /* larger than the largest value in the last range */
354
- if (DatumGetBool (compar ))
355
- continue ;
356
-
357
- start = 0 ; /* first range */
358
- end = ranges -> nranges - 1 ; /* last range */
359
- while (true)
327
+ for (i = 0 ; i < ranges -> nvalues ; i ++ )
360
328
{
361
- int midpoint = (start + end ) / 2 ;
362
-
363
- /* this means we ran out of ranges in the last step */
364
- if (start > end )
365
- break ;
329
+ Datum compar ;
330
+ int start ,
331
+ end ;
332
+ Datum minvalue = ranges -> values [0 ];
333
+ Datum maxvalue = ranges -> values [2 * ranges -> nranges - 1 ];
334
+ Datum value = ranges -> values [2 * ranges -> nranges + i ];
366
335
367
- /* copy the min/max values from the ranges */
368
- minvalue = ranges -> values [2 * midpoint ];
369
- maxvalue = ranges -> values [2 * midpoint + 1 ];
336
+ compar = FunctionCall2Coll (cmpFn , colloid , value , minvalue );
370
337
371
338
/*
372
- * Is the value smaller than the minval? If yes, we'll recurse to
373
- * the left side of range array .
339
+ * If the value is smaller than the lower bound in the first range
340
+ * then it cannot possibly be in any of the ranges .
374
341
*/
375
- compar = FunctionCall2Coll (cmpFn , colloid , value , minvalue );
376
-
377
- /* smaller than the smallest value in this range */
378
342
if (DatumGetBool (compar ))
379
- {
380
- end = (midpoint - 1 );
381
343
continue ;
382
- }
383
344
384
- /*
385
- * Is the value greater than the minval? If yes, we'll recurse to
386
- * the right side of range array.
387
- */
388
345
compar = FunctionCall2Coll (cmpFn , colloid , maxvalue , value );
389
346
390
- /* larger than the largest value in this range */
347
+ /*
348
+ * Likewise, if the value is larger than the upper bound of the
349
+ * final range, then it cannot possibly be inside any of the
350
+ * ranges.
351
+ */
391
352
if (DatumGetBool (compar ))
392
- {
393
- start = (midpoint + 1 );
394
353
continue ;
395
- }
396
354
397
- /* hey, we found a matching range */
398
- Assert (false);
355
+ /* bsearch the ranges to see if 'value' fits within any of them */
356
+ start = 0 ; /* first range */
357
+ end = ranges -> nranges - 1 ; /* last range */
358
+ while (true)
359
+ {
360
+ int midpoint = (start + end ) / 2 ;
361
+
362
+ /* this means we ran out of ranges in the last step */
363
+ if (start > end )
364
+ break ;
365
+
366
+ /* copy the min/max values from the ranges */
367
+ minvalue = ranges -> values [2 * midpoint ];
368
+ maxvalue = ranges -> values [2 * midpoint + 1 ];
369
+
370
+ /*
371
+ * Is the value smaller than the minval? If yes, we'll recurse
372
+ * to the left side of range array.
373
+ */
374
+ compar = FunctionCall2Coll (cmpFn , colloid , value , minvalue );
375
+
376
+ /* smaller than the smallest value in this range */
377
+ if (DatumGetBool (compar ))
378
+ {
379
+ end = (midpoint - 1 );
380
+ continue ;
381
+ }
382
+
383
+ /*
384
+ * Is the value greater than the minval? If yes, we'll recurse
385
+ * to the right side of range array.
386
+ */
387
+ compar = FunctionCall2Coll (cmpFn , colloid , maxvalue , value );
388
+
389
+ /* larger than the largest value in this range */
390
+ if (DatumGetBool (compar ))
391
+ {
392
+ start = (midpoint + 1 );
393
+ continue ;
394
+ }
395
+
396
+ /* hey, we found a matching range */
397
+ Assert (false);
398
+ }
399
399
}
400
400
}
401
401
402
- /* and values in the unsorted part must not be in sorted part */
403
- for ( i = ranges -> nsorted ; i < ranges -> nvalues ; i ++ )
402
+ /* and values in the unsorted part must not be in the sorted part */
403
+ if ( ranges -> nsorted > 0 )
404
404
{
405
405
compare_context cxt ;
406
- Datum value = ranges -> values [2 * ranges -> nranges + i ];
407
-
408
- if (ranges -> nsorted == 0 )
409
- break ;
410
406
411
407
cxt .colloid = ranges -> colloid ;
412
408
cxt .cmpFn = ranges -> cmp ;
413
409
414
- Assert (bsearch_arg (& value , & ranges -> values [2 * ranges -> nranges ],
415
- ranges -> nsorted , sizeof (Datum ),
416
- compare_values , (void * ) & cxt ) == NULL );
410
+ for (i = ranges -> nsorted ; i < ranges -> nvalues ; i ++ )
411
+ {
412
+ Datum value = ranges -> values [2 * ranges -> nranges + i ];
413
+
414
+ Assert (bsearch_arg (& value , & ranges -> values [2 * ranges -> nranges ],
415
+ ranges -> nsorted , sizeof (Datum ),
416
+ compare_values , (void * ) & cxt ) == NULL );
417
+ }
417
418
}
418
419
#endif
419
420
}
@@ -923,8 +924,8 @@ has_matching_range(BrinDesc *bdesc, Oid colloid, Ranges *ranges,
923
924
{
924
925
Datum compar ;
925
926
926
- Datum minvalue = ranges -> values [ 0 ] ;
927
- Datum maxvalue = ranges -> values [ 2 * ranges -> nranges - 1 ] ;
927
+ Datum minvalue ;
928
+ Datum maxvalue ;
928
929
929
930
FmgrInfo * cmpLessFn ;
930
931
FmgrInfo * cmpGreaterFn ;
@@ -936,6 +937,9 @@ has_matching_range(BrinDesc *bdesc, Oid colloid, Ranges *ranges,
936
937
if (ranges -> nranges == 0 )
937
938
return false;
938
939
940
+ minvalue = ranges -> values [0 ];
941
+ maxvalue = ranges -> values [2 * ranges -> nranges - 1 ];
942
+
939
943
/*
940
944
* Otherwise, need to compare the new value with boundaries of all the
941
945
* ranges. First check if it's less than the absolute minimum, which is
0 commit comments