Header And Logo

PostgreSQL
| The world's most advanced open source database.

sortsupport.c

Go to the documentation of this file.
00001 /*-------------------------------------------------------------------------
00002  *
00003  * sortsupport.c
00004  *    Support routines for accelerated sorting.
00005  *
00006  *
00007  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
00008  * Portions Copyright (c) 1994, Regents of the University of California
00009  *
00010  * IDENTIFICATION
00011  *    src/backend/utils/sort/sortsupport.c
00012  *
00013  *-------------------------------------------------------------------------
00014  */
00015 
00016 #include "postgres.h"
00017 
00018 /* See sortsupport.h */
00019 #define SORTSUPPORT_INCLUDE_DEFINITIONS
00020 
00021 #include "fmgr.h"
00022 #include "utils/lsyscache.h"
00023 #include "utils/sortsupport.h"
00024 
00025 
00026 /* Info needed to use an old-style comparison function as a sort comparator */
00027 typedef struct
00028 {
00029     FunctionCallInfoData fcinfo;    /* reusable callinfo structure */
00030     FmgrInfo    flinfo;         /* lookup data for comparison function */
00031 } SortShimExtra;
00032 
00033 
00034 /*
00035  * Shim function for calling an old-style comparator
00036  *
00037  * This is essentially an inlined version of FunctionCall2Coll(), except
00038  * we assume that the FunctionCallInfoData was already mostly set up by
00039  * PrepareSortSupportComparisonShim.
00040  */
00041 static int
00042 comparison_shim(Datum x, Datum y, SortSupport ssup)
00043 {
00044     SortShimExtra *extra = (SortShimExtra *) ssup->ssup_extra;
00045     Datum       result;
00046 
00047     extra->fcinfo.arg[0] = x;
00048     extra->fcinfo.arg[1] = y;
00049 
00050     /* just for paranoia's sake, we reset isnull each time */
00051     extra->fcinfo.isnull = false;
00052 
00053     result = FunctionCallInvoke(&extra->fcinfo);
00054 
00055     /* Check for null result, since caller is clearly not expecting one */
00056     if (extra->fcinfo.isnull)
00057         elog(ERROR, "function %u returned NULL", extra->flinfo.fn_oid);
00058 
00059     return result;
00060 }
00061 
00062 /*
00063  * Set up a shim function to allow use of an old-style btree comparison
00064  * function as if it were a sort support comparator.
00065  */
00066 void
00067 PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup)
00068 {
00069     SortShimExtra *extra;
00070 
00071     extra = (SortShimExtra *) MemoryContextAlloc(ssup->ssup_cxt,
00072                                                  sizeof(SortShimExtra));
00073 
00074     /* Lookup the comparison function */
00075     fmgr_info_cxt(cmpFunc, &extra->flinfo, ssup->ssup_cxt);
00076 
00077     /* We can initialize the callinfo just once and re-use it */
00078     InitFunctionCallInfoData(extra->fcinfo, &extra->flinfo, 2,
00079                              ssup->ssup_collation, NULL, NULL);
00080     extra->fcinfo.argnull[0] = false;
00081     extra->fcinfo.argnull[1] = false;
00082 
00083     ssup->ssup_extra = extra;
00084     ssup->comparator = comparison_shim;
00085 }
00086 
00087 /*
00088  * Fill in SortSupport given an ordering operator (btree "<" or ">" operator).
00089  *
00090  * Caller must previously have zeroed the SortSupportData structure and then
00091  * filled in ssup_cxt, ssup_collation, and ssup_nulls_first.  This will fill
00092  * in ssup_reverse as well as the comparator function pointer.
00093  */
00094 void
00095 PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
00096 {
00097     Oid         sortFunction;
00098     bool        issupport;
00099 
00100     if (!get_sort_function_for_ordering_op(orderingOp,
00101                                            &sortFunction,
00102                                            &issupport,
00103                                            &ssup->ssup_reverse))
00104         elog(ERROR, "operator %u is not a valid ordering operator",
00105              orderingOp);
00106 
00107     if (issupport)
00108     {
00109         /* The sort support function should provide a comparator */
00110         OidFunctionCall1(sortFunction, PointerGetDatum(ssup));
00111         Assert(ssup->comparator != NULL);
00112     }
00113     else
00114     {
00115         /* We'll use a shim to call the old-style btree comparator */
00116         PrepareSortSupportComparisonShim(sortFunction, ssup);
00117     }
00118 }