1 /*-------------------------------------------------------------------------
4 * Support routines for accelerated sorting.
7 * Portions Copyright (c) 1996-2012, PostgreSQL Global Development Group
8 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/backend/utils/sort/sortsupport.c
13 *-------------------------------------------------------------------------
19 #include "utils/lsyscache.h"
20 #include "utils/sortsupport.h"
23 /* Info needed to use an old-style comparison function as a sort comparator */
26 FunctionCallInfoData fcinfo; /* reusable callinfo structure */
27 FmgrInfo flinfo; /* lookup data for comparison function */
32 * sortsupport.h defines inline versions of these functions if allowed by the
33 * compiler; in which case the definitions below are skipped.
38 * Apply a sort comparator function and return a 3-way comparison result.
39 * This takes care of handling reverse-sort and NULLs-ordering properly.
42 ApplySortComparator(Datum datum1, bool isNull1,
43 Datum datum2, bool isNull2,
51 compare = 0; /* NULL "=" NULL */
52 else if (ssup->ssup_nulls_first)
53 compare = -1; /* NULL "<" NOT_NULL */
55 compare = 1; /* NULL ">" NOT_NULL */
59 if (ssup->ssup_nulls_first)
60 compare = 1; /* NOT_NULL ">" NULL */
62 compare = -1; /* NOT_NULL "<" NULL */
66 compare = (*ssup->comparator) (datum1, datum2, ssup);
67 if (ssup->ssup_reverse)
74 #endif /* ! USE_INLINE */
77 * Shim function for calling an old-style comparator
79 * This is essentially an inlined version of FunctionCall2Coll(), except
80 * we assume that the FunctionCallInfoData was already mostly set up by
81 * PrepareSortSupportComparisonShim.
84 comparison_shim(Datum x, Datum y, SortSupport ssup)
86 SortShimExtra *extra = (SortShimExtra *) ssup->ssup_extra;
89 extra->fcinfo.arg[0] = x;
90 extra->fcinfo.arg[1] = y;
92 /* just for paranoia's sake, we reset isnull each time */
93 extra->fcinfo.isnull = false;
95 result = FunctionCallInvoke(&extra->fcinfo);
97 /* Check for null result, since caller is clearly not expecting one */
98 if (extra->fcinfo.isnull)
99 elog(ERROR, "function %u returned NULL", extra->flinfo.fn_oid);
105 * Set up a shim function to allow use of an old-style btree comparison
106 * function as if it were a sort support comparator.
109 PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup)
111 SortShimExtra *extra;
113 extra = (SortShimExtra *) MemoryContextAlloc(ssup->ssup_cxt,
114 sizeof(SortShimExtra));
116 /* Lookup the comparison function */
117 fmgr_info_cxt(cmpFunc, &extra->flinfo, ssup->ssup_cxt);
119 /* We can initialize the callinfo just once and re-use it */
120 InitFunctionCallInfoData(extra->fcinfo, &extra->flinfo, 2,
121 ssup->ssup_collation, NULL, NULL);
122 extra->fcinfo.argnull[0] = false;
123 extra->fcinfo.argnull[1] = false;
125 ssup->ssup_extra = extra;
126 ssup->comparator = comparison_shim;
130 * Fill in SortSupport given an ordering operator (btree "<" or ">" operator).
132 * Caller must previously have zeroed the SortSupportData structure and then
133 * filled in ssup_cxt, ssup_collation, and ssup_nulls_first. This will fill
134 * in ssup_reverse as well as the comparator function pointer.
137 PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
142 if (!get_sort_function_for_ordering_op(orderingOp,
145 &ssup->ssup_reverse))
146 elog(ERROR, "operator %u is not a valid ordering operator",
151 /* The sort support function should provide a comparator */
152 OidFunctionCall1(sortFunction, PointerGetDatum(ssup));
153 Assert(ssup->comparator != NULL);
157 /* We'll use a shim to call the old-style btree comparator */
158 PrepareSortSupportComparisonShim(sortFunction, ssup);