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

Generated by: LCOV version 1.14