3131#define RANGESTRAT_CONTAINS 7
3232#define RANGESTRAT_CONTAINED_BY 8
3333#define RANGESTRAT_CONTAINS_ELEM 16
34- #define RANGESTRAT_ELEM_CONTAINED_BY 17
3534#define RANGESTRAT_EQ 18
3635#define RANGESTRAT_NE 19
3736
@@ -48,11 +47,11 @@ typedef struct
4847static RangeType * range_super_union (TypeCacheEntry * typcache ,RangeType * r1 ,
4948RangeType * r2 );
5049static bool range_gist_consistent_int (FmgrInfo * flinfo ,
51- StrategyNumber strategy ,RangeType * key ,
52- RangeType * query );
50+ StrategyNumber strategy ,RangeType * key ,
51+ Datum query );
5352static bool range_gist_consistent_leaf (FmgrInfo * flinfo ,
54- StrategyNumber strategy ,RangeType * key ,
55- RangeType * query );
53+ StrategyNumber strategy ,RangeType * key ,
54+ Datum query );
5655static int sort_item_cmp (const void * a ,const void * b );
5756
5857
@@ -61,39 +60,15 @@ Datum
6160range_gist_consistent (PG_FUNCTION_ARGS )
6261{
6362GISTENTRY * entry = (GISTENTRY * )PG_GETARG_POINTER (0 );
64- Datum dquery = PG_GETARG_DATUM (1 );
63+ Datum query = PG_GETARG_DATUM (1 );
6564StrategyNumber strategy = (StrategyNumber )PG_GETARG_UINT16 (2 );
6665/* Oid subtype = PG_GETARG_OID(3); */
6766bool * recheck = (bool * )PG_GETARG_POINTER (4 );
6867RangeType * key = DatumGetRangeType (entry -> key );
69- TypeCacheEntry * typcache ;
70- RangeType * query ;
7168
7269/* All operators served by this function are exact */
7370* recheck = false;
7471
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-
9772if (GIST_LEAF (entry ))
9873PG_RETURN_BOOL (range_gist_consistent_leaf (fcinfo -> flinfo ,strategy ,
9974key ,query ));
@@ -170,21 +145,23 @@ range_gist_penalty(PG_FUNCTION_ARGS)
170145
171146subtype_diff = & typcache -> rng_subdiff_finfo ;
172147
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+ */
174153s_union = range_super_union (typcache ,orig ,new );
175154
176155range_deserialize (typcache ,orig ,& lower1 ,& upper1 ,& empty1 );
177156range_deserialize (typcache ,s_union ,& lower2 ,& upper2 ,& empty2 );
178157
179- /* if orig isn't empty, s_union can't be either */
180- Assert (empty1 || !empty2 );
181-
158+ /* handle cases where orig is empty */
182159if (empty1 && empty2 )
183160{
184161* penalty = 0 ;
185162PG_RETURN_POINTER (penalty );
186163}
187- else if (empty1 && ! empty2 )
164+ else if (empty1 )
188165{
189166if (lower2 .infinite || upper2 .infinite )
190167{
@@ -199,6 +176,7 @@ range_gist_penalty(PG_FUNCTION_ARGS)
199176typcache -> rng_collation ,
200177upper2 .val ,
201178lower2 .val ));
179+ /* upper2 must be >= lower2 */
202180if (* penalty < 0 )
203181* penalty = 0 ;/* subtype_diff is broken */
204182PG_RETURN_POINTER (penalty );
@@ -211,46 +189,53 @@ range_gist_penalty(PG_FUNCTION_ARGS)
211189}
212190}
213191
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 */
214196Assert (lower2 .infinite || !lower1 .infinite );
215197
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 )
219199lower_diff = 0 ;
200+ else if (lower2 .infinite )
201+ lower_diff = get_float8_infinity ();
220202else if (OidIsValid (subtype_diff -> fn_oid ))
221203{
222204lower_diff = DatumGetFloat8 (FunctionCall2Coll (subtype_diff ,
223205typcache -> rng_collation ,
224206lower1 .val ,
225207lower2 .val ));
208+ /* orig's lower bound must be >= s_union's */
226209if (lower_diff < 0 )
227210lower_diff = 0 ;/* subtype_diff is broken */
228211}
229212else
230213{
231214/* 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 ;
233216}
234217
218+ /* similarly, if orig's upper bound is infinite, s_union's must be too */
235219Assert (upper2 .infinite || !upper1 .infinite );
236220
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 )
240222upper_diff = 0 ;
223+ else if (upper2 .infinite )
224+ upper_diff = get_float8_infinity ();
241225else if (OidIsValid (subtype_diff -> fn_oid ))
242226{
243227upper_diff = DatumGetFloat8 (FunctionCall2Coll (subtype_diff ,
244228typcache -> rng_collation ,
245229upper2 .val ,
246230upper1 .val ));
231+ /* orig's upper bound must be <= s_union's */
247232if (upper_diff < 0 )
248233upper_diff = 0 ;/* subtype_diff is broken */
249234}
250235else
251236{
252237/* 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 ;
254239}
255240
256241Assert (lower_diff >=0 && upper_diff >=0 );
@@ -450,7 +435,7 @@ TrickFunctionCall2(PGFunction proc, FmgrInfo *flinfo, Datum arg1, Datum arg2)
450435 */
451436static bool
452437range_gist_consistent_int (FmgrInfo * flinfo ,StrategyNumber strategy ,
453- RangeType * key ,RangeType * query )
438+ RangeType * key ,Datum query )
454439{
455440PGFunction proc ;
456441bool negate = false;
@@ -486,22 +471,23 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
486471negate = true;
487472break ;
488473case RANGESTRAT_ADJACENT :
489- if (RangeIsEmpty (key )|| RangeIsEmpty (query ))
474+ if (RangeIsEmpty (key )|| RangeIsEmpty (DatumGetRangeType ( query ) ))
490475return false;
491476if (DatumGetBool (TrickFunctionCall2 (range_adjacent ,flinfo ,
492477RangeTypeGetDatum (key ),
493- RangeTypeGetDatum ( query ) )))
478+ query )))
494479return true;
495480proc = range_overlaps ;
496481break ;
497482case RANGESTRAT_CONTAINS :
498- case RANGESTRAT_CONTAINS_ELEM :
499483proc = range_contains ;
500484break ;
501485case RANGESTRAT_CONTAINED_BY :
502- case RANGESTRAT_ELEM_CONTAINED_BY :
503486return true;
504487break ;
488+ case RANGESTRAT_CONTAINS_ELEM :
489+ proc = range_contains_elem ;
490+ break ;
505491case RANGESTRAT_EQ :
506492proc = range_contains ;
507493break ;
@@ -516,7 +502,7 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
516502
517503retval = DatumGetBool (TrickFunctionCall2 (proc ,flinfo ,
518504RangeTypeGetDatum (key ),
519- RangeTypeGetDatum ( query ) ));
505+ query ));
520506if (negate )
521507retval = !retval ;
522508
@@ -528,48 +514,39 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
528514 */
529515static bool
530516range_gist_consistent_leaf (FmgrInfo * flinfo ,StrategyNumber strategy ,
531- RangeType * key ,RangeType * query )
517+ RangeType * key ,Datum query )
532518{
533519PGFunction proc ;
534520
535521switch (strategy )
536522{
537523case RANGESTRAT_BEFORE :
538- if (RangeIsEmpty (key )|| RangeIsEmpty (query ))
539- return false;
540524proc = range_before ;
541525break ;
542526case RANGESTRAT_OVERLEFT :
543- if (RangeIsEmpty (key )|| RangeIsEmpty (query ))
544- return false;
545527proc = range_overleft ;
546528break ;
547529case RANGESTRAT_OVERLAPS :
548530proc = range_overlaps ;
549531break ;
550532case RANGESTRAT_OVERRIGHT :
551- if (RangeIsEmpty (key )|| RangeIsEmpty (query ))
552- return false;
553533proc = range_overright ;
554534break ;
555535case RANGESTRAT_AFTER :
556- if (RangeIsEmpty (key )|| RangeIsEmpty (query ))
557- return false;
558536proc = range_after ;
559537break ;
560538case RANGESTRAT_ADJACENT :
561- if (RangeIsEmpty (key )|| RangeIsEmpty (query ))
562- return false;
563539proc = range_adjacent ;
564540break ;
565541case RANGESTRAT_CONTAINS :
566- case RANGESTRAT_CONTAINS_ELEM :
567542proc = range_contains ;
568543break ;
569544case RANGESTRAT_CONTAINED_BY :
570- case RANGESTRAT_ELEM_CONTAINED_BY :
571545proc = range_contained_by ;
572546break ;
547+ case RANGESTRAT_CONTAINS_ELEM :
548+ proc = range_contains_elem ;
549+ break ;
573550case RANGESTRAT_EQ :
574551proc = range_eq ;
575552break ;
@@ -584,7 +561,7 @@ range_gist_consistent_leaf(FmgrInfo *flinfo, StrategyNumber strategy,
584561
585562return DatumGetBool (TrickFunctionCall2 (proc ,flinfo ,
586563RangeTypeGetDatum (key ),
587- RangeTypeGetDatum ( query ) ));
564+ query ));
588565}
589566
590567/*
@@ -649,7 +626,7 @@ sort_item_cmp(const void *a, const void *b)
649626else if (lower2 .infinite )
650627return 1 ;
651628else if (upper1 .infinite && upper2 .infinite )
652- return -1 * range_cmp_bounds (typcache ,& lower1 ,& lower2 );
629+ return - ( range_cmp_bounds (typcache ,& lower1 ,& lower2 ) );
653630else if (upper1 .infinite )
654631return 1 ;
655632else if (upper2 .infinite )