31
31
#define RANGESTRAT_CONTAINS 7
32
32
#define RANGESTRAT_CONTAINED_BY 8
33
33
#define RANGESTRAT_CONTAINS_ELEM 16
34
- #define RANGESTRAT_ELEM_CONTAINED_BY 17
35
34
#define RANGESTRAT_EQ 18
36
35
#define RANGESTRAT_NE 19
37
36
@@ -48,11 +47,11 @@ typedef struct
48
47
static RangeType * range_super_union (TypeCacheEntry * typcache , RangeType * r1 ,
49
48
RangeType * r2 );
50
49
static bool range_gist_consistent_int (FmgrInfo * flinfo ,
51
- StrategyNumber strategy , RangeType * key ,
52
- RangeType * query );
50
+ StrategyNumber strategy , RangeType * key ,
51
+ Datum query );
53
52
static bool range_gist_consistent_leaf (FmgrInfo * flinfo ,
54
- StrategyNumber strategy , RangeType * key ,
55
- RangeType * query );
53
+ StrategyNumber strategy , RangeType * key ,
54
+ Datum query );
56
55
static int sort_item_cmp (const void * a , const void * b );
57
56
58
57
@@ -61,39 +60,15 @@ Datum
61
60
range_gist_consistent (PG_FUNCTION_ARGS )
62
61
{
63
62
GISTENTRY * entry = (GISTENTRY * ) PG_GETARG_POINTER (0 );
64
- Datum dquery = PG_GETARG_DATUM (1 );
63
+ Datum query = PG_GETARG_DATUM (1 );
65
64
StrategyNumber strategy = (StrategyNumber ) PG_GETARG_UINT16 (2 );
66
65
/* Oid subtype = PG_GETARG_OID(3); */
67
66
bool * recheck = (bool * ) PG_GETARG_POINTER (4 );
68
67
RangeType * key = DatumGetRangeType (entry -> key );
69
- TypeCacheEntry * typcache ;
70
- RangeType * query ;
71
68
72
69
/* All operators served by this function are exact */
73
70
* recheck = false;
74
71
75
- switch (strategy )
76
- {
77
- /*
78
- * For element contains and contained by operators, the other operand
79
- * is a "point" of the subtype. Construct a singleton range
80
- * containing just that value. (Since range_contains_elem and
81
- * elem_contained_by_range would do that anyway, it's actually more
82
- * efficient not less so to merge these cases into range containment
83
- * at this step. But revisit this if we ever change the implementation
84
- * of those functions.)
85
- */
86
- case RANGESTRAT_CONTAINS_ELEM :
87
- case RANGESTRAT_ELEM_CONTAINED_BY :
88
- typcache = range_get_typcache (fcinfo , RangeTypeGetOid (key ));
89
- query = make_singleton_range (typcache , dquery );
90
- break ;
91
-
92
- default :
93
- query = DatumGetRangeType (dquery );
94
- break ;
95
- }
96
-
97
72
if (GIST_LEAF (entry ))
98
73
PG_RETURN_BOOL (range_gist_consistent_leaf (fcinfo -> flinfo , strategy ,
99
74
key , query ));
@@ -170,21 +145,23 @@ range_gist_penalty(PG_FUNCTION_ARGS)
170
145
171
146
subtype_diff = & typcache -> rng_subdiff_finfo ;
172
147
173
- /* we want to compare the size of "orig" to size of "orig union new" */
148
+ /*
149
+ * We want to compare the size of "orig" to size of "orig union new".
150
+ * The penalty will be the sum of the reduction in the lower bound plus
151
+ * the increase in the upper bound.
152
+ */
174
153
s_union = range_super_union (typcache , orig , new );
175
154
176
155
range_deserialize (typcache , orig , & lower1 , & upper1 , & empty1 );
177
156
range_deserialize (typcache , s_union , & lower2 , & upper2 , & empty2 );
178
157
179
- /* if orig isn't empty, s_union can't be either */
180
- Assert (empty1 || !empty2 );
181
-
158
+ /* handle cases where orig is empty */
182
159
if (empty1 && empty2 )
183
160
{
184
161
* penalty = 0 ;
185
162
PG_RETURN_POINTER (penalty );
186
163
}
187
- else if (empty1 && ! empty2 )
164
+ else if (empty1 )
188
165
{
189
166
if (lower2 .infinite || upper2 .infinite )
190
167
{
@@ -199,6 +176,7 @@ range_gist_penalty(PG_FUNCTION_ARGS)
199
176
typcache -> rng_collation ,
200
177
upper2 .val ,
201
178
lower2 .val ));
179
+ /* upper2 must be >= lower2 */
202
180
if (* penalty < 0 )
203
181
* penalty = 0 ; /* subtype_diff is broken */
204
182
PG_RETURN_POINTER (penalty );
@@ -211,46 +189,53 @@ range_gist_penalty(PG_FUNCTION_ARGS)
211
189
}
212
190
}
213
191
192
+ /* if orig isn't empty, s_union can't be either */
193
+ Assert (!empty2 );
194
+
195
+ /* similarly, if orig's lower bound is infinite, s_union's must be too */
214
196
Assert (lower2 .infinite || !lower1 .infinite );
215
19
F438
7
216
- if (lower2 .infinite && !lower1 .infinite )
217
- lower_diff = get_float8_infinity ();
218
- else if (lower2 .infinite && lower1 .infinite )
198
+ if (lower2 .infinite && lower1 .infinite )
219
199
lower_diff = 0 ;
200
+ else if (lower2 .infinite )
201
+ lower_diff = get_float8_infinity ();
220
202
else if (OidIsValid (subtype_diff -> fn_oid ))
221
203
{
222
204
lower_diff = DatumGetFloat8 (FunctionCall2Coll (subtype_diff ,
223
205
typcache -> rng_collation ,
224
206
lower1 .val ,
225
207
lower2 .val ));
208
+ /* orig's lower bound must be >= s_union's */
226
209
if (lower_diff < 0 )
227
210
lower_diff = 0 ; /* subtype_diff is broken */
228
211
}
229
212
else
230
213
{
231
214
/* only know whether there is a difference or not */
232
- lower_diff = ( float ) range_cmp_bounds (typcache , & lower1 , & lower2 );
215
+ lower_diff = range_cmp_bounds (typcache , & lower1 , & lower2 ) > 0 ? 1 : 0 ;
233
216
}
234
217
218
+ /* similarly, if orig's upper bound is infinite, s_union's must be too */
235
219
Assert (upper2 .infinite || !upper1 .infinite );
236
220
237
- if (upper2 .infinite && !upper1 .infinite )
238
- upper_diff = get_float8_infinity ();
239
- else if (upper2 .infinite && upper1 .infinite )
221
+ if (upper2 .infinite && upper1 .infinite )
240
222
upper_diff = 0 ;
223
+ else if (upper2 .infinite )
224
+ upper_diff = get_float8_infinity ();
241
225
else if (OidIsValid (subtype_diff -> fn_oid ))
242
226
{
243
227
upper_diff = DatumGetFloat8 (FunctionCall2Coll (subtype_diff ,
244
228
typcache -> rng_collation ,
245
229
upper2 .val ,
246
230
upper1 .val ));
231
+ /* orig's upper bound must be <= s_union's */
247
232
if (upper_diff < 0 )
248
233
upper_diff = 0 ; /* subtype_diff is broken */
249
234
}
250
235
else
251
236
{
252
237
/* only know whether there is a difference or not */
253
- upper_diff = ( float ) range_cmp_bounds (typcache , & upper2 , & upper1 );
238
+ upper_diff = range_cmp_bounds (typcache , & upper2 , & upper1 ) > 0 ? 1 : 0 ;
254
239
}
255
240
256
241
Assert (lower_diff >= 0 && upper_diff >= 0 );
@@ -450,7 +435,7 @@ TrickFunctionCall2(PGFunction proc, FmgrInfo *flinfo, Datum arg1, Datum arg2)
450
435
*/
451
436
static bool
452
437
range_gist_consistent_int (FmgrInfo * flinfo , StrategyNumber strategy ,
453
- RangeType * key , RangeType * query )
438
+ RangeType * key , Datum query )
454
439
{
455
440
PGFunction proc ;
456
441
bool negate = false;
@@ -486,22 +471,23 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
486
471
negate = true;
487
472
break ;
488
473
case RANGESTRAT_ADJACENT :
489
- if (RangeIsEmpty (key ) || RangeIsEmpty (query ))
474
+ if (RangeIsEmpty (key ) || RangeIsEmpty (DatumGetRangeType ( query ) ))
490
475
return false;
491
476
if (DatumGetBool (TrickFunctionCall2 (range_adjacent , flinfo ,
492
477
RangeTypeGetDatum (key ),
493
- RangeTypeGetDatum ( query ) )))
478
+ query )))
494
479
return true;
495
480
proc = range_overlaps ;
496
481
break ;
497
482
case RANGESTRAT_CONTAINS :
498
- case RANGESTRAT_CONTAINS_ELEM :
499
483
proc = range_contains ;
500
484
break ;
501
485
case RANGESTRAT_CONTAINED_BY :
502
- case RANGESTRAT_ELEM_CONTAINED_BY :
503
486
return true;
504
487
break ;
488
+ case RANGESTRAT_CONTAINS_ELEM :
489
+ proc = range_contains_elem ;
490
+ break ;
505
491
case RANGESTRAT_EQ :
506
492
proc = range_contains ;
507
493
break ;
@@ -516,7 +502,7 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
516
502
517
503
retval = DatumGetBool (TrickFunctionCall2 (proc , flinfo ,
518
504
RangeTypeGetDatum (key ),
519
- RangeTypeGetDatum ( query ) ));
505
+ query ));
520
506
if (negate )
521
507
retval = !retval ;
522
508
@@ -528,48 +514,39 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
528
514
*/
529
515
static bool
530
516
range_gist_consistent_leaf (FmgrInfo * flinfo , StrategyNumber strategy ,
531
- RangeType * key , RangeType * query )
517
+ RangeType * key , Datum query )
532
518
{
533
519
PGFunction proc ;
534
520
535
521
switch (strategy )
536
522
{
537
523
case RANGESTRAT_BEFORE :
538
- if (RangeIsEmpty (key ) || RangeIsEmpty (query ))
539
- return false;
540
524
proc = range_before ;
541
525
break ;
542
526
case RANGESTRAT_OVERLEFT :
543
- if (RangeIsEmpty (key ) || RangeIsEmpty (query ))
544
- return false;
545
527
proc = range_overleft ;
546
528
break ;
547
529
case RANGESTRAT_OVERLAPS :
548
530
proc = range_overlaps ;
549
531
break ;
550
532
case RANGESTRAT_OVERRIGHT :
551
- if (RangeIsEmpty (key ) || RangeIsEmpty (query ))
552
- return false;
553
533
proc = range_overright ;
554
534
break ;
555
535
case RANGESTRAT_AFTER :
556
- if (RangeIsEmpty (key ) || RangeIsEmpty (query ))
557
- return false;
558
536
proc = range_after ;
559
537
break ;
560
538
case RANGESTRAT_ADJACENT :
561
- if (RangeIsEmpty (key ) || RangeIsEmpty (query ))
562
- return false;
563
539
proc = range_adjacent ;
564
540
break ;
565
541
case RANGESTRAT_CONTAINS :
566
- case RANGESTRAT_CONTAINS_ELEM :
567
542
proc = range_contains ;
568
543
break ;
569
544
case RANGESTRAT_CONTAINED_BY :
570
- case RANGESTRAT_ELEM_CONTAINED_BY :
571
545
proc = range_contained_by ;
572
546
break ;
547
+ case RANGESTRAT_CONTAINS_ELEM :
548
+ proc = range_contains_elem ;
549
+ break ;
573
550
case RANGESTRAT_EQ :
574
551
proc = range_eq ;
575
552
break ;
@@ -584,7 +561,7 @@ range_gist_consistent_leaf(FmgrInfo *flinfo, StrategyNumber strategy,
584
561
585
562
return DatumGetBool (TrickFunctionCall2 (proc , flinfo ,
586
563
RangeTypeGetDatum (key ),
587
- RangeTypeGetDatum ( query ) ));
564
+ query ));
588
565
}
589
566
590
567
/*
@@ -649,7 +626,7 @@ sort_item_cmp(const void *a, const void *b)
649
626
else if (lower2 .infinite )
650
627
return 1 ;
651
628
else if (upper1 .infinite && upper2 .infinite )
652
- return -1 * range_cmp_bounds (typcache , & lower1 , & lower2 );
629
+ return - ( range_cmp_bounds (typcache , & lower1 , & lower2 ) );
653
630
else if (upper1 .infinite )
654
631
return 1 ;
655
632
else if (upper2 .infinite )
0 commit comments