LCOV - code coverage report
Current view: top level - src/backend/utils/sort - sortsupport.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 88.7 % 53 47
Test Date: 2026-02-17 17:20:33 Functions: 100.0 % 6 6
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * sortsupport.c
       4              :  *    Support routines for accelerated sorting.
       5              :  *
       6              :  *
       7              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       8              :  * Portions Copyright (c) 1994, Regents of the University of California
       9              :  *
      10              :  * IDENTIFICATION
      11              :  *    src/backend/utils/sort/sortsupport.c
      12              :  *
      13              :  *-------------------------------------------------------------------------
      14              :  */
      15              : 
      16              : #include "postgres.h"
      17              : 
      18              : #include "access/gist.h"
      19              : #include "access/nbtree.h"
      20              : #include "fmgr.h"
      21              : #include "utils/lsyscache.h"
      22              : #include "utils/rel.h"
      23              : #include "utils/sortsupport.h"
      24              : 
      25              : 
      26              : /* Info needed to use an old-style comparison function as a sort comparator */
      27              : typedef struct
      28              : {
      29              :     FmgrInfo    flinfo;         /* lookup data for comparison function */
      30              :     FunctionCallInfoBaseData fcinfo;    /* reusable callinfo structure */
      31              : } SortShimExtra;
      32              : 
      33              : #define SizeForSortShimExtra(nargs) (offsetof(SortShimExtra, fcinfo) + SizeForFunctionCallInfo(nargs))
      34              : 
      35              : /*
      36              :  * Shim function for calling an old-style comparator
      37              :  *
      38              :  * This is essentially an inlined version of FunctionCall2Coll(), except
      39              :  * we assume that the FunctionCallInfoBaseData was already mostly set up by
      40              :  * PrepareSortSupportComparisonShim.
      41              :  */
      42              : static int
      43     76008768 : comparison_shim(Datum x, Datum y, SortSupport ssup)
      44              : {
      45     76008768 :     SortShimExtra *extra = (SortShimExtra *) ssup->ssup_extra;
      46              :     Datum       result;
      47              : 
      48     76008768 :     extra->fcinfo.args[0].value = x;
      49     76008768 :     extra->fcinfo.args[1].value = y;
      50              : 
      51              :     /* just for paranoia's sake, we reset isnull each time */
      52     76008768 :     extra->fcinfo.isnull = false;
      53              : 
      54     76008768 :     result = FunctionCallInvoke(&extra->fcinfo);
      55              : 
      56              :     /* Check for null result, since caller is clearly not expecting one */
      57     76008765 :     if (extra->fcinfo.isnull)
      58            0 :         elog(ERROR, "function %u returned NULL", extra->flinfo.fn_oid);
      59              : 
      60     76008765 :     return DatumGetInt32(result);
      61              : }
      62              : 
      63              : /*
      64              :  * Set up a shim function to allow use of an old-style btree comparison
      65              :  * function as if it were a sort support comparator.
      66              :  */
      67              : void
      68        17798 : PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup)
      69              : {
      70              :     SortShimExtra *extra;
      71              : 
      72        17798 :     extra = (SortShimExtra *) MemoryContextAlloc(ssup->ssup_cxt,
      73              :                                                  SizeForSortShimExtra(2));
      74              : 
      75              :     /* Lookup the comparison function */
      76        17798 :     fmgr_info_cxt(cmpFunc, &extra->flinfo, ssup->ssup_cxt);
      77              : 
      78              :     /* We can initialize the callinfo just once and re-use it */
      79        17798 :     InitFunctionCallInfoData(extra->fcinfo, &extra->flinfo, 2,
      80              :                              ssup->ssup_collation, NULL, NULL);
      81        17798 :     extra->fcinfo.args[0].isnull = false;
      82        17798 :     extra->fcinfo.args[1].isnull = false;
      83              : 
      84        17798 :     ssup->ssup_extra = extra;
      85        17798 :     ssup->comparator = comparison_shim;
      86        17798 : }
      87              : 
      88              : /*
      89              :  * Look up and call sortsupport function to setup SortSupport comparator;
      90              :  * or if no such function exists or it declines to set up the appropriate
      91              :  * state, prepare a suitable shim.
      92              :  */
      93              : static void
      94       246801 : FinishSortSupportFunction(Oid opfamily, Oid opcintype, SortSupport ssup)
      95              : {
      96              :     Oid         sortSupportFunction;
      97              : 
      98              :     /* Look for a sort support function */
      99       246801 :     sortSupportFunction = get_opfamily_proc(opfamily, opcintype, opcintype,
     100              :                                             BTSORTSUPPORT_PROC);
     101       246801 :     if (OidIsValid(sortSupportFunction))
     102              :     {
     103              :         /*
     104              :          * The sort support function can provide a comparator, but it can also
     105              :          * choose not to so (e.g. based on the selected collation).
     106              :          */
     107       229408 :         OidFunctionCall1(sortSupportFunction, PointerGetDatum(ssup));
     108              :     }
     109              : 
     110       246795 :     if (ssup->comparator == NULL)
     111              :     {
     112              :         Oid         sortFunction;
     113              : 
     114        17393 :         sortFunction = get_opfamily_proc(opfamily, opcintype, opcintype,
     115              :                                          BTORDER_PROC);
     116              : 
     117        17393 :         if (!OidIsValid(sortFunction))
     118            0 :             elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
     119              :                  BTORDER_PROC, opcintype, opcintype, opfamily);
     120              : 
     121              :         /* We'll use a shim to call the old-style btree comparator */
     122        17393 :         PrepareSortSupportComparisonShim(sortFunction, ssup);
     123              :     }
     124       246795 : }
     125              : 
     126              : /*
     127              :  * Fill in SortSupport given an ordering operator (btree "<" or ">" operator).
     128              :  *
     129              :  * Caller must previously have zeroed the SortSupportData structure and then
     130              :  * filled in ssup_cxt, ssup_collation, and ssup_nulls_first.  This will fill
     131              :  * in ssup_reverse as well as the comparator function pointer.
     132              :  */
     133              : void
     134       167486 : PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
     135              : {
     136              :     Oid         opfamily;
     137              :     Oid         opcintype;
     138              :     CompareType cmptype;
     139              : 
     140              :     Assert(ssup->comparator == NULL);
     141              : 
     142              :     /* Find the operator in pg_amop */
     143       167486 :     if (!get_ordering_op_properties(orderingOp, &opfamily, &opcintype,
     144              :                                     &cmptype))
     145            0 :         elog(ERROR, "operator %u is not a valid ordering operator",
     146              :              orderingOp);
     147       167486 :     ssup->ssup_reverse = (cmptype == COMPARE_GT);
     148              : 
     149       167486 :     FinishSortSupportFunction(opfamily, opcintype, ssup);
     150       167480 : }
     151              : 
     152              : /*
     153              :  * Fill in SortSupport given an index relation and attribute.
     154              :  *
     155              :  * Caller must previously have zeroed the SortSupportData structure and then
     156              :  * filled in ssup_cxt, ssup_attno, ssup_collation, and ssup_nulls_first.  This
     157              :  * will fill in ssup_reverse (based on the supplied argument), as well as the
     158              :  * comparator function pointer.
     159              :  */
     160              : void
     161        79315 : PrepareSortSupportFromIndexRel(Relation indexRel, bool reverse,
     162              :                                SortSupport ssup)
     163              : {
     164        79315 :     Oid         opfamily = indexRel->rd_opfamily[ssup->ssup_attno - 1];
     165        79315 :     Oid         opcintype = indexRel->rd_opcintype[ssup->ssup_attno - 1];
     166              : 
     167              :     Assert(ssup->comparator == NULL);
     168              : 
     169        79315 :     if (!indexRel->rd_indam->amcanorder)
     170            0 :         elog(ERROR, "unexpected non-amcanorder AM: %u", indexRel->rd_rel->relam);
     171        79315 :     ssup->ssup_reverse = reverse;
     172              : 
     173        79315 :     FinishSortSupportFunction(opfamily, opcintype, ssup);
     174        79315 : }
     175              : 
     176              : /*
     177              :  * Fill in SortSupport given a GiST index relation
     178              :  *
     179              :  * Caller must previously have zeroed the SortSupportData structure and then
     180              :  * filled in ssup_cxt, ssup_attno, ssup_collation, and ssup_nulls_first.  This
     181              :  * will fill in ssup_reverse (always false for GiST index build), as well as
     182              :  * the comparator function pointer.
     183              :  */
     184              : void
     185          719 : PrepareSortSupportFromGistIndexRel(Relation indexRel, SortSupport ssup)
     186              : {
     187          719 :     Oid         opfamily = indexRel->rd_opfamily[ssup->ssup_attno - 1];
     188          719 :     Oid         opcintype = indexRel->rd_opcintype[ssup->ssup_attno - 1];
     189              :     Oid         sortSupportFunction;
     190              : 
     191              :     Assert(ssup->comparator == NULL);
     192              : 
     193          719 :     if (indexRel->rd_rel->relam != GIST_AM_OID)
     194            0 :         elog(ERROR, "unexpected non-gist AM: %u", indexRel->rd_rel->relam);
     195          719 :     ssup->ssup_reverse = false;
     196              : 
     197              :     /*
     198              :      * Look up the sort support function. This is simpler than for B-tree
     199              :      * indexes because we don't support the old-style btree comparators.
     200              :      */
     201          719 :     sortSupportFunction = get_opfamily_proc(opfamily, opcintype, opcintype,
     202              :                                             GIST_SORTSUPPORT_PROC);
     203          719 :     if (!OidIsValid(sortSupportFunction))
     204            0 :         elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
     205              :              GIST_SORTSUPPORT_PROC, opcintype, opcintype, opfamily);
     206          719 :     OidFunctionCall1(sortSupportFunction, PointerGetDatum(ssup));
     207          719 : }
        

Generated by: LCOV version 2.0-1