From a7a4add6c4243cbcf50a554bce4c34cb72a344b5 Mon Sep 17 00:00:00 2001 From: Heikki Linnakangas Date: Wed, 18 Jul 2012 22:34:06 +0300 Subject: [PATCH] Refactor the way code is shared between some range type functions. 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 | 219 +++++++++++++++--------- src/backend/utils/adt/rangetypes_gist.c | 168 ++++++------------ src/include/utils/rangetypes.h | 24 +++ 3 files changed, 220 insertions(+), 191 deletions(-) diff --git a/src/backend/utils/adt/rangetypes.c b/src/backend/utils/adt/rangetypes.c index 658fbf6193..c2f0b2559b 100644 --- a/src/backend/utils/adt/rangetypes.c +++ b/src/backend/utils/adt/rangetypes.c @@ -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; diff --git a/src/backend/utils/adt/rangetypes_gist.c b/src/backend/utils/adt/rangetypes_gist.c index 16103f854b..21f0ebabc7 100644 --- a/src/backend/utils/adt/rangetypes_gist.c +++ b/src/backend/utils/adt/rangetypes_gist.c @@ -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)); } /* diff --git a/src/include/utils/rangetypes.h b/src/include/utils/rangetypes.h index ad72df57dd..a37401c8ec 100644 --- a/src/include/utils/rangetypes.h +++ b/src/include/utils/rangetypes.h @@ -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); -- 2.40.0