]> granicus.if.org Git - postgresql/commitdiff
Refactor the way code is shared between some range type functions.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 18 Jul 2012 19:34:06 +0000 (22:34 +0300)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 18 Jul 2012 20:14:56 +0000 (23:14 +0300)
Functions like range_eq, range_before etc. are exposed at the SQL-level, but
they're also used internally by the GiST consistent support function. The
code sharing was done by a hack, TrickFunctionCall2, which relied on the
knowledge that all the functions used fn_extra the same way. This commit
splits the functions into internal versions that take a TypeCacheEntry as
argument, and thin wrappers to expose the functions at the SQL-level. The
internal versions can then be called directly and in a less hacky way from
the GiST consistent function.

This is just cosmetic, but backpatch to 9.2 anyway, to avoid having a
different version of this code in the 9.2 branch. That would make
backpatching fixes in this area more difficult.

Alexander Korotkov

src/backend/utils/adt/rangetypes.c
src/backend/utils/adt/rangetypes_gist.c
src/include/utils/rangetypes.h

index 658fbf6193d0b66583e15ad2ac85c9f2523c4932..c2f0b2559b7faa59e7e837a544d1f4483551c6d4 100644 (file)
@@ -63,10 +63,6 @@ static const char *range_parse_bound(const char *string, const char *ptr,
 static char *range_deparse(char flags, const char *lbound_str,
                          const char *ubound_str);
 static char *range_bound_escape(const char *value);
-static bool range_contains_internal(TypeCacheEntry *typcache,
-                                               RangeType *r1, RangeType *r2);
-static bool range_contains_elem_internal(TypeCacheEntry *typcache,
-                                                        RangeType *r, Datum val);
 static Size datum_compute_size(Size sz, Datum datum, bool typbyval,
                                   char typalign, int16 typlen, char typstorage);
 static Pointer datum_write(Pointer ptr, Datum datum, bool typbyval,
@@ -546,13 +542,10 @@ elem_contained_by_range(PG_FUNCTION_ARGS)
 
 /* range, range -> bool functions */
 
-/* equality */
-Datum
-range_eq(PG_FUNCTION_ARGS)
+/* equality (internal version) */
+bool
+range_eq_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
 {
-       RangeType  *r1 = PG_GETARG_RANGE(0);
-       RangeType  *r2 = PG_GETARG_RANGE(1);
-       TypeCacheEntry *typcache;
        RangeBound      lower1,
                                lower2;
        RangeBound      upper1,
@@ -564,32 +557,54 @@ range_eq(PG_FUNCTION_ARGS)
        if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
                elog(ERROR, "range types do not match");
 
-       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
-
        range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
        range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
 
        if (empty1 && empty2)
-               PG_RETURN_BOOL(true);
+               return true;
        if (empty1 != empty2)
-               PG_RETURN_BOOL(false);
+               return false;
 
        if (range_cmp_bounds(typcache, &lower1, &lower2) != 0)
-               PG_RETURN_BOOL(false);
+               return false;
 
        if (range_cmp_bounds(typcache, &upper1, &upper2) != 0)
-               PG_RETURN_BOOL(false);
+               return false;
+
+       return true;
+}
 
-       PG_RETURN_BOOL(true);
+/* equality */
+Datum
+range_eq(PG_FUNCTION_ARGS)
+{
+       RangeType  *r1 = PG_GETARG_RANGE(0);
+       RangeType  *r2 = PG_GETARG_RANGE(1);
+       TypeCacheEntry *typcache;
+
+       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
+
+       PG_RETURN_BOOL(range_eq_internal(typcache, r1, r2));
+}
+
+/* inequality (internal version) */
+bool
+range_ne_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
+{
+       return (!range_eq_internal(typcache, r1, r2));
 }
 
 /* inequality */
 Datum
 range_ne(PG_FUNCTION_ARGS)
 {
-       bool            eq = DatumGetBool(range_eq(fcinfo));
+       RangeType  *r1 = PG_GETARG_RANGE(0);
+       RangeType  *r2 = PG_GETARG_RANGE(1);
+       TypeCacheEntry *typcache;
+
+       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
 
-       PG_RETURN_BOOL(!eq);
+       PG_RETURN_BOOL(range_ne_internal(typcache, r1, r2));
 }
 
 /* contains? */
@@ -600,10 +615,6 @@ range_contains(PG_FUNCTION_ARGS)
        RangeType  *r2 = PG_GETARG_RANGE(1);
        TypeCacheEntry *typcache;
 
-       /* Different types should be prevented by ANYRANGE matching rules */
-       if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
-               elog(ERROR, "range types do not match");
-
        typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
 
        PG_RETURN_BOOL(range_contains_internal(typcache, r1, r2));
@@ -617,22 +628,15 @@ range_contained_by(PG_FUNCTION_ARGS)
        RangeType  *r2 = PG_GETARG_RANGE(1);
        TypeCacheEntry *typcache;
 
-       /* Different types should be prevented by ANYRANGE matching rules */
-       if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
-               elog(ERROR, "range types do not match");
-
        typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
 
-       PG_RETURN_BOOL(range_contains_internal(typcache, r2, r1));
+       PG_RETURN_BOOL(range_contained_by_internal(typcache, r1, r2));
 }
 
-/* strictly left of? */
-Datum
-range_before(PG_FUNCTION_ARGS)
+/* strictly left of? (internal version) */
+bool
+range_before_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
 {
-       RangeType  *r1 = PG_GETARG_RANGE(0);
-       RangeType  *r2 = PG_GETARG_RANGE(1);
-       TypeCacheEntry *typcache;
        RangeBound      lower1,
                                lower2;
        RangeBound      upper1,
@@ -644,25 +648,33 @@ range_before(PG_FUNCTION_ARGS)
        if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
                elog(ERROR, "range types do not match");
 
-       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
-
        range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
        range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
 
        /* An empty range is neither before nor after any other range */
        if (empty1 || empty2)
-               PG_RETURN_BOOL(false);
+               return false;
 
-       PG_RETURN_BOOL(range_cmp_bounds(typcache, &upper1, &lower2) < 0);
+       return (range_cmp_bounds(typcache, &upper1, &lower2) < 0);
 }
 
-/* strictly right of? */
+/* strictly left of? */
 Datum
-range_after(PG_FUNCTION_ARGS)
+range_before(PG_FUNCTION_ARGS)
 {
        RangeType  *r1 = PG_GETARG_RANGE(0);
        RangeType  *r2 = PG_GETARG_RANGE(1);
        TypeCacheEntry *typcache;
+
+       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
+
+       PG_RETURN_BOOL(range_before_internal(typcache, r1, r2));
+}
+
+/* strictly right of? (internal version) */
+bool
+range_after_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
+{
        RangeBound      lower1,
                                lower2;
        RangeBound      upper1,
@@ -674,25 +686,33 @@ range_after(PG_FUNCTION_ARGS)
        if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
                elog(ERROR, "range types do not match");
 
-       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
-
        range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
        range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
 
        /* An empty range is neither before nor after any other range */
        if (empty1 || empty2)
-               PG_RETURN_BOOL(false);
+               return false;
 
-       PG_RETURN_BOOL(range_cmp_bounds(typcache, &lower1, &upper2) > 0);
+       return (range_cmp_bounds(typcache, &lower1, &upper2) > 0);
 }
 
-/* adjacent to (but not overlapping)? */
+/* strictly right of? */
 Datum
-range_adjacent(PG_FUNCTION_ARGS)
+range_after(PG_FUNCTION_ARGS)
 {
        RangeType  *r1 = PG_GETARG_RANGE(0);
        RangeType  *r2 = PG_GETARG_RANGE(1);
        TypeCacheEntry *typcache;
+
+       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
+
+       PG_RETURN_BOOL(range_after_internal(typcache, r1, r2));
+}
+
+/* adjacent to (but not overlapping)? (internal version) */
+bool
+range_adjacent_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
+{
        RangeBound      lower1,
                                lower2;
        RangeBound      upper1,
@@ -706,14 +726,12 @@ range_adjacent(PG_FUNCTION_ARGS)
        if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
                elog(ERROR, "range types do not match");
 
-       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
-
        range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
        range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
 
        /* An empty range is not adjacent to any other range */
        if (empty1 || empty2)
-               PG_RETURN_BOOL(false);
+               return false;
 
        /*
         * Given two ranges A..B and C..D, where B < C, the ranges are adjacent if
@@ -736,7 +754,7 @@ range_adjacent(PG_FUNCTION_ARGS)
        {
                /* in a continuous subtype, there are assumed to be points between */
                if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
-                       PG_RETURN_BOOL(false);
+                       return (false);
                /* flip the inclusion flags */
                upper1.inclusive = !upper1.inclusive;
                lower2.inclusive = !lower2.inclusive;
@@ -744,11 +762,11 @@ range_adjacent(PG_FUNCTION_ARGS)
                upper1.lower = true;
                lower2.lower = false;
                r3 = make_range(typcache, &upper1, &lower2, false);
-               PG_RETURN_BOOL(RangeIsEmpty(r3));
+               return RangeIsEmpty(r3);
        }
        if (cmp == 0)
        {
-               PG_RETURN_BOOL(upper1.inclusive != lower2.inclusive);
+               return (upper1.inclusive != lower2.inclusive);
        }
 
        cmp = range_cmp_bound_values(typcache, &upper2, &lower1);
@@ -756,7 +774,7 @@ range_adjacent(PG_FUNCTION_ARGS)
        {
                /* in a continuous subtype, there are assumed to be points between */
                if (!OidIsValid(typcache->rng_canonical_finfo.fn_oid))
-                       PG_RETURN_BOOL(false);
+                       return (false);
                /* flip the inclusion flags */
                upper2.inclusive = !upper2.inclusive;
                lower1.inclusive = !lower1.inclusive;
@@ -764,23 +782,33 @@ range_adjacent(PG_FUNCTION_ARGS)
                upper2.lower = true;
                lower1.lower = false;
                r3 = make_range(typcache, &upper2, &lower1, false);
-               PG_RETURN_BOOL(RangeIsEmpty(r3));
+               return RangeIsEmpty(r3);
        }
        if (cmp == 0)
        {
-               PG_RETURN_BOOL(upper2.inclusive != lower1.inclusive);
+               return (upper2.inclusive != lower1.inclusive);
        }
 
-       PG_RETURN_BOOL(false);
+       return false;
 }
 
-/* overlaps? */
+/* adjacent to (but not overlapping)? */
 Datum
-range_overlaps(PG_FUNCTION_ARGS)
+range_adjacent(PG_FUNCTION_ARGS)
 {
        RangeType  *r1 = PG_GETARG_RANGE(0);
        RangeType  *r2 = PG_GETARG_RANGE(1);
        TypeCacheEntry *typcache;
+
+       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
+
+       PG_RETURN_BOOL(range_adjacent_internal(typcache, r1, r2));
+}
+
+/* overlaps? (internal version) */
+bool
+range_overlaps_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
+{
        RangeBound      lower1,
                                lower2;
        RangeBound      upper1,
@@ -792,33 +820,41 @@ range_overlaps(PG_FUNCTION_ARGS)
        if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
                elog(ERROR, "range types do not match");
 
-       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
-
        range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
        range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
 
        /* An empty range does not overlap any other range */
        if (empty1 || empty2)
-               PG_RETURN_BOOL(false);
+               return false;
 
        if (range_cmp_bounds(typcache, &lower1, &lower2) >= 0 &&
                range_cmp_bounds(typcache, &lower1, &upper2) <= 0)
-               PG_RETURN_BOOL(true);
+               return true;
 
        if (range_cmp_bounds(typcache, &lower2, &lower1) >= 0 &&
                range_cmp_bounds(typcache, &lower2, &upper1) <= 0)
-               PG_RETURN_BOOL(true);
+               return true;
 
-       PG_RETURN_BOOL(false);
+       return false;
 }
 
-/* does not extend to right of? */
+/* overlaps? */
 Datum
-range_overleft(PG_FUNCTION_ARGS)
+range_overlaps(PG_FUNCTION_ARGS)
 {
        RangeType  *r1 = PG_GETARG_RANGE(0);
        RangeType  *r2 = PG_GETARG_RANGE(1);
        TypeCacheEntry *typcache;
+
+       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
+
+       PG_RETURN_BOOL(range_overlaps_internal(typcache, r1, r2));
+}
+
+/* does not extend to right of? (internal version) */
+bool
+range_overleft_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
+{
        RangeBound      lower1,
                                lower2;
        RangeBound      upper1,
@@ -830,28 +866,36 @@ range_overleft(PG_FUNCTION_ARGS)
        if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
                elog(ERROR, "range types do not match");
 
-       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
-
        range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
        range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
 
        /* An empty range is neither before nor after any other range */
        if (empty1 || empty2)
-               PG_RETURN_BOOL(false);
+               return false;
 
        if (range_cmp_bounds(typcache, &upper1, &upper2) <= 0)
-               PG_RETURN_BOOL(true);
+               return true;
 
-       PG_RETURN_BOOL(false);
+       return false;
 }
 
-/* does not extend to left of? */
+/* does not extend to right of? */
 Datum
-range_overright(PG_FUNCTION_ARGS)
+range_overleft(PG_FUNCTION_ARGS)
 {
        RangeType  *r1 = PG_GETARG_RANGE(0);
        RangeType  *r2 = PG_GETARG_RANGE(1);
        TypeCacheEntry *typcache;
+
+       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
+
+       PG_RETURN_BOOL(range_overleft_internal(typcache, r1, r2));
+}
+
+/* does not extend to left of? (internal version) */
+bool
+range_overright_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
+{
        RangeBound      lower1,
                                lower2;
        RangeBound      upper1,
@@ -863,8 +907,6 @@ range_overright(PG_FUNCTION_ARGS)
        if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
                elog(ERROR, "range types do not match");
 
-       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
-
        range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
        range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
 
@@ -878,6 +920,19 @@ range_overright(PG_FUNCTION_ARGS)
        PG_RETURN_BOOL(false);
 }
 
+/* does not extend to left of? */
+Datum
+range_overright(PG_FUNCTION_ARGS)
+{
+       RangeType  *r1 = PG_GETARG_RANGE(0);
+       RangeType  *r2 = PG_GETARG_RANGE(1);
+       TypeCacheEntry *typcache;
+
+       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
+
+       PG_RETURN_BOOL(range_overright_internal(typcache, r1, r2));
+}
+
 
 /* range, range -> range functions */
 
@@ -2152,7 +2207,7 @@ range_bound_escape(const char *value)
  * Caller has already checked that they are the same range type, and looked up
  * the necessary typcache entry.
  */
-static bool
+bool
 range_contains_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
 {
        RangeBound      lower1;
@@ -2162,6 +2217,10 @@ range_contains_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
        RangeBound      upper2;
        bool            empty2;
 
+       /* Different types should be prevented by ANYRANGE matching rules */
+       if (RangeTypeGetOid(r1) != RangeTypeGetOid(r2))
+               elog(ERROR, "range types do not match");
+
        range_deserialize(typcache, r1, &lower1, &upper1, &empty1);
        range_deserialize(typcache, r2, &lower2, &upper2, &empty2);
 
@@ -2180,10 +2239,16 @@ range_contains_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
        return true;
 }
 
+bool
+range_contained_by_internal(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
+{
+       return range_contains_internal(typcache, r2, r1);
+}
+
 /*
  * Test whether range r contains a specific element value.
  */
-static bool
+bool
 range_contains_elem_internal(TypeCacheEntry *typcache, RangeType *r, Datum val)
 {
        RangeBound      lower;
index 16103f854bcb92b27cb03ea96a170423164ea5f8..21f0ebabc782c28633f1dae4699ee29df5011260 100644 (file)
@@ -148,10 +148,10 @@ typedef struct
 
 static RangeType *range_super_union(TypeCacheEntry *typcache, RangeType *r1,
                                  RangeType *r2);
-static bool range_gist_consistent_int(FmgrInfo *flinfo,
+static bool range_gist_consistent_int(TypeCacheEntry *typcache,
                                                  StrategyNumber strategy, RangeType *key,
                                                  Datum query);
-static bool range_gist_consistent_leaf(FmgrInfo *flinfo,
+static bool range_gist_consistent_leaf(TypeCacheEntry *typcache,
                                                   StrategyNumber strategy, RangeType *key,
                                                   Datum query);
 static void range_gist_fallback_split(TypeCacheEntry *typcache,
@@ -191,15 +191,18 @@ range_gist_consistent(PG_FUNCTION_ARGS)
        /* Oid subtype = PG_GETARG_OID(3); */
        bool       *recheck = (bool *) PG_GETARG_POINTER(4);
        RangeType  *key = DatumGetRangeType(entry->key);
+       TypeCacheEntry *typcache;
 
        /* All operators served by this function are exact */
        *recheck = false;
 
+       typcache = range_get_typcache(fcinfo, RangeTypeGetOid(key));
+
        if (GIST_LEAF(entry))
-               PG_RETURN_BOOL(range_gist_consistent_leaf(fcinfo->flinfo, strategy,
+               PG_RETURN_BOOL(range_gist_consistent_leaf(typcache, strategy,
                                                                                                  key, query));
        else
-               PG_RETURN_BOOL(range_gist_consistent_int(fcinfo->flinfo, strategy,
+               PG_RETURN_BOOL(range_gist_consistent_int(typcache, strategy,
                                                                                                 key, query));
 }
 
@@ -686,12 +689,10 @@ range_gist_same(PG_FUNCTION_ARGS)
                *result = false;
        else
        {
-               /*
-                * We can safely call range_eq using our fcinfo directly; it won't
-                * notice the third argument.  This allows it to use fn_extra for
-                * caching.
-                */
-               *result = DatumGetBool(range_eq(fcinfo));
+               TypeCacheEntry *typcache;
+               typcache = range_get_typcache(fcinfo, RangeTypeGetOid(r1));
+
+               *result = range_eq_internal(typcache, r1, r2);
        }
 
        PG_RETURN_POINTER(result);
@@ -780,91 +781,49 @@ range_super_union(TypeCacheEntry *typcache, RangeType *r1, RangeType *r2)
        return result;
 }
 
-/*
- * trick function call: call the given function with given FmgrInfo
- *
- * To allow the various functions called here to cache lookups of range
- * datatype information, we use a trick: we pass them the FmgrInfo struct
- * for the GiST consistent function.  This relies on the knowledge that
- * none of them consult FmgrInfo for anything but fn_extra, and that they
- * all use fn_extra the same way, i.e. as a pointer to the typcache entry
- * for the range data type.  Since the FmgrInfo is long-lived (it's actually
- * part of the relcache entry for the index, typically) this essentially
- * eliminates lookup overhead during operations on a GiST range index.
- */
-static Datum
-TrickFunctionCall2(PGFunction proc, FmgrInfo *flinfo, Datum arg1, Datum arg2)
-{
-       FunctionCallInfoData fcinfo;
-       Datum           result;
-
-       InitFunctionCallInfoData(fcinfo, flinfo, 2, InvalidOid, NULL, NULL);
-
-       fcinfo.arg[0] = arg1;
-       fcinfo.arg[1] = arg2;
-       fcinfo.argnull[0] = false;
-       fcinfo.argnull[1] = false;
-
-       result = (*proc) (&fcinfo);
-
-       if (fcinfo.isnull)
-               elog(ERROR, "function %p returned NULL", proc);
-
-       return result;
-}
-
 /*
  * GiST consistent test on an index internal page
  */
 static bool
-range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
+range_gist_consistent_int(TypeCacheEntry *typcache, StrategyNumber strategy,
                                                  RangeType *key, Datum query)
 {
-       PGFunction      proc;
-       bool            negate = false;
-       bool            retval;
-
        switch (strategy)
        {
                case RANGESTRAT_BEFORE:
                        if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeType(query)))
                                return false;
-                       proc = range_overright;
-                       negate = true;
-                       break;
+                       return (!range_overright_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query)));
                case RANGESTRAT_OVERLEFT:
                        if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeType(query)))
                                return false;
-                       proc = range_after;
-                       negate = true;
-                       break;
+                       return (!range_after_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query)));
                case RANGESTRAT_OVERLAPS:
-                       proc = range_overlaps;
-                       break;
+                       return range_overlaps_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_OVERRIGHT:
                        if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeType(query)))
                                return false;
-                       proc = range_before;
-                       negate = true;
-                       break;
+                       return (!range_before_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query)));
                case RANGESTRAT_AFTER:
                        if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeType(query)))
                                return false;
-                       proc = range_overleft;
-                       negate = true;
-                       break;
+                       return (!range_overleft_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query)));
                case RANGESTRAT_ADJACENT:
                        if (RangeIsEmpty(key) || RangeIsEmpty(DatumGetRangeType(query)))
                                return false;
-                       if (DatumGetBool(TrickFunctionCall2(range_adjacent, flinfo,
-                                                                                               RangeTypeGetDatum(key),
-                                                                                               query)))
+                       if (range_adjacent_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query)))
                                return true;
-                       proc = range_overlaps;
-                       break;
+                       return range_overlaps_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_CONTAINS:
-                       proc = range_contains;
-                       break;
+                       return range_contains_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_CONTAINED_BY:
 
                        /*
@@ -874,11 +833,10 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
                         */
                        if (RangeIsOrContainsEmpty(key))
                                return true;
-                       proc = range_overlaps;
-                       break;
+                       return range_overlaps_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_CONTAINS_ELEM:
-                       proc = range_contains_elem;
-                       break;
+                       return range_contains_elem_internal(typcache, key, query);
                case RANGESTRAT_EQ:
 
                        /*
@@ -887,73 +845,55 @@ range_gist_consistent_int(FmgrInfo *flinfo, StrategyNumber strategy,
                         */
                        if (RangeIsEmpty(DatumGetRangeType(query)))
                                return RangeIsOrContainsEmpty(key);
-                       proc = range_contains;
-                       break;
+                       return range_contains_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                default:
                        elog(ERROR, "unrecognized range strategy: %d", strategy);
-                       proc = NULL;            /* keep compiler quiet */
-                       break;
+                       return false;                   /* keep compiler quiet */
        }
-
-       retval = DatumGetBool(TrickFunctionCall2(proc, flinfo,
-                                                                                        RangeTypeGetDatum(key),
-                                                                                        query));
-       if (negate)
-               retval = !retval;
-
-       return retval;
 }
 
 /*
  * GiST consistent test on an index leaf page
  */
 static bool
-range_gist_consistent_leaf(FmgrInfo *flinfo, StrategyNumber strategy,
+range_gist_consistent_leaf(TypeCacheEntry *typcache, StrategyNumber strategy,
                                                   RangeType *key, Datum query)
 {
-       PGFunction      proc;
-
        switch (strategy)
        {
                case RANGESTRAT_BEFORE:
-                       proc = range_before;
-                       break;
+                       return range_before_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_OVERLEFT:
-                       proc = range_overleft;
-                       break;
+                       return range_overleft_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_OVERLAPS:
-                       proc = range_overlaps;
-                       break;
+                       return range_overlaps_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_OVERRIGHT:
-                       proc = range_overright;
-                       break;
+                       return range_overright_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_AFTER:
-                       proc = range_after;
-                       break;
+                       return range_after_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_ADJACENT:
-                       proc = range_adjacent;
-                       break;
+                       return range_adjacent_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_CONTAINS:
-                       proc = range_contains;
-                       break;
+                       return range_contains_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_CONTAINED_BY:
-                       proc = range_contained_by;
-                       break;
+                       return range_contained_by_internal(typcache, key,
+                                                                                                       DatumGetRangeType(query));
                case RANGESTRAT_CONTAINS_ELEM:
-                       proc = range_contains_elem;
-                       break;
+                       return range_contains_elem_internal(typcache, key, query);
                case RANGESTRAT_EQ:
-                       proc = range_eq;
-                       break;
+                       return range_eq_internal(typcache, key, DatumGetRangeType(query));
                default:
                        elog(ERROR, "unrecognized range strategy: %d", strategy);
-                       proc = NULL;            /* keep compiler quiet */
-                       break;
+                       return false;                   /* keep compiler quiet */
        }
-
-       return DatumGetBool(TrickFunctionCall2(proc, flinfo,
-                                                                                  RangeTypeGetDatum(key),
-                                                                                  query));
 }
 
 /*
index ad72df57dd61f1acb18b8ceb9e48bf28ffe51600..a37401c8ec91aa9b966150a472775c6c44b90e4d 100644 (file)
@@ -104,6 +104,8 @@ extern Datum range_upper_inf(PG_FUNCTION_ARGS);
 extern Datum range_contains_elem(PG_FUNCTION_ARGS);
 extern Datum elem_contained_by_range(PG_FUNCTION_ARGS);
 
+extern bool range_contains_elem_internal(TypeCacheEntry *typcache, RangeType *r, Datum val);
+
 /* range, range -> bool */
 extern Datum range_eq(PG_FUNCTION_ARGS);
 extern Datum range_ne(PG_FUNCTION_ARGS);
@@ -116,6 +118,28 @@ extern Datum range_overlaps(PG_FUNCTION_ARGS);
 extern Datum range_overleft(PG_FUNCTION_ARGS);
 extern Datum range_overright(PG_FUNCTION_ARGS);
 
+/* internal versions of the above */
+extern bool range_eq_internal(TypeCacheEntry *typcache, RangeType *r1,
+                                 RangeType *r2);
+extern bool range_ne_internal(TypeCacheEntry *typcache, RangeType *r1,
+                                 RangeType *r2);
+extern bool range_contains_internal(TypeCacheEntry *typcache, RangeType *r1,
+                                               RangeType *r2);
+extern bool range_contained_by_internal(TypeCacheEntry *typcache, RangeType *r1,
+                                                       RangeType *r2);
+extern bool range_before_internal(TypeCacheEntry *typcache, RangeType *r1,
+                                         RangeType *r2);
+extern bool range_after_internal(TypeCacheEntry *typcache, RangeType *r1,
+                                        RangeType *r2);
+extern bool range_adjacent_internal(TypeCacheEntry *typcache, RangeType *r1,
+                                               RangeType *r2);
+extern bool range_overlaps_internal(TypeCacheEntry *typcache, RangeType *r1,
+                                               RangeType *r2);
+extern bool range_overleft_internal(TypeCacheEntry *typcache, RangeType *r1,
+                                               RangeType *r2);
+extern bool range_overright_internal(TypeCacheEntry *typcache, RangeType *r1,
+                                                RangeType *r2);
+
 /* range, range -> range */
 extern Datum range_minus(PG_FUNCTION_ARGS);
 extern Datum range_union(PG_FUNCTION_ARGS);