LCOV - differential code coverage report
Current view: top level - src/backend/utils/sort - sortsupport.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 87.9 % 58 51 7 51
Current Date: 2023-04-08 15:15:32 Functions: 100.0 % 6 6 6
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * sortsupport.c
       4                 :  *    Support routines for accelerated sorting.
       5                 :  *
       6                 :  *
       7                 :  * Portions Copyright (c) 1996-2023, 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 CBC   218941097 : comparison_shim(Datum x, Datum y, SortSupport ssup)
      45                 : {
      46       218941097 :     SortShimExtra *extra = (SortShimExtra *) ssup->ssup_extra;
      47                 :     Datum       result;
      48                 : 
      49       218941097 :     extra->fcinfo.args[0].value = x;
      50       218941097 :     extra->fcinfo.args[1].value = y;
      51                 : 
      52                 :     /* just for paranoia's sake, we reset isnull each time */
      53       218941097 :     extra->fcinfo.isnull = false;
      54                 : 
      55       218941097 :     result = FunctionCallInvoke(&extra->fcinfo);
      56                 : 
      57                 :     /* Check for null result, since caller is clearly not expecting one */
      58       218941097 :     if (extra->fcinfo.isnull)
      59 UBC           0 :         elog(ERROR, "function %u returned NULL", extra->flinfo.fn_oid);
      60                 : 
      61 CBC   218941097 :     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           45317 : PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup)
      70                 : {
      71                 :     SortShimExtra *extra;
      72                 : 
      73           45317 :     extra = (SortShimExtra *) MemoryContextAlloc(ssup->ssup_cxt,
      74                 :                                                  SizeForSortShimExtra(2));
      75                 : 
      76                 :     /* Lookup the comparison function */
      77           45317 :     fmgr_info_cxt(cmpFunc, &extra->flinfo, ssup->ssup_cxt);
      78                 : 
      79                 :     /* We can initialize the callinfo just once and re-use it */
      80           45317 :     InitFunctionCallInfoData(extra->fcinfo, &extra->flinfo, 2,
      81                 :                              ssup->ssup_collation, NULL, NULL);
      82           45317 :     extra->fcinfo.args[0].isnull = false;
      83           45317 :     extra->fcinfo.args[1].isnull = false;
      84                 : 
      85           45317 :     ssup->ssup_extra = extra;
      86           45317 :     ssup->comparator = comparison_shim;
      87           45317 : }
      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          423529 : FinishSortSupportFunction(Oid opfamily, Oid opcintype, SortSupport ssup)
      96                 : {
      97                 :     Oid         sortSupportFunction;
      98                 : 
      99                 :     /* Look for a sort support function */
     100          423529 :     sortSupportFunction = get_opfamily_proc(opfamily, opcintype, opcintype,
     101                 :                                             BTSORTSUPPORT_PROC);
     102          423529 :     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          378411 :         OidFunctionCall1(sortSupportFunction, PointerGetDatum(ssup));
     109                 :     }
     110                 : 
     111          423520 :     if (ssup->comparator == NULL)
     112                 :     {
     113                 :         Oid         sortFunction;
     114                 : 
     115           45118 :         sortFunction = get_opfamily_proc(opfamily, opcintype, opcintype,
     116                 :                                          BTORDER_PROC);
     117                 : 
     118           45118 :         if (!OidIsValid(sortFunction))
     119 UBC           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 CBC       45118 :         PrepareSortSupportComparisonShim(sortFunction, ssup);
     124                 :     }
     125          423520 : }
     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          216309 : PrepareSortSupportFromOrderingOp(Oid orderingOp, SortSupport ssup)
     136                 : {
     137                 :     Oid         opfamily;
     138                 :     Oid         opcintype;
     139                 :     int16       strategy;
     140                 : 
     141          216309 :     Assert(ssup->comparator == NULL);
     142                 : 
     143                 :     /* Find the operator in pg_amop */
     144          216309 :     if (!get_ordering_op_properties(orderingOp, &opfamily, &opcintype,
     145                 :                                     &strategy))
     146 UBC           0 :         elog(ERROR, "operator %u is not a valid ordering operator",
     147                 :              orderingOp);
     148 CBC      216309 :     ssup->ssup_reverse = (strategy == BTGreaterStrategyNumber);
     149                 : 
     150          216309 :     FinishSortSupportFunction(opfamily, opcintype, ssup);
     151          216300 : }
     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          207220 : PrepareSortSupportFromIndexRel(Relation indexRel, int16 strategy,
     163                 :                                SortSupport ssup)
     164                 : {
     165          207220 :     Oid         opfamily = indexRel->rd_opfamily[ssup->ssup_attno - 1];
     166          207220 :     Oid         opcintype = indexRel->rd_opcintype[ssup->ssup_attno - 1];
     167                 : 
     168          207220 :     Assert(ssup->comparator == NULL);
     169                 : 
     170          207220 :     if (indexRel->rd_rel->relam != BTREE_AM_OID)
     171 UBC           0 :         elog(ERROR, "unexpected non-btree AM: %u", indexRel->rd_rel->relam);
     172 CBC      207220 :     if (strategy != BTGreaterStrategyNumber &&
     173                 :         strategy != BTLessStrategyNumber)
     174 UBC           0 :         elog(ERROR, "unexpected sort support strategy: %d", strategy);
     175 CBC      207220 :     ssup->ssup_reverse = (strategy == BTGreaterStrategyNumber);
     176                 : 
     177          207220 :     FinishSortSupportFunction(opfamily, opcintype, ssup);
     178          207220 : }
     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              69 : PrepareSortSupportFromGistIndexRel(Relation indexRel, SortSupport ssup)
     190                 : {
     191              69 :     Oid         opfamily = indexRel->rd_opfamily[ssup->ssup_attno - 1];
     192              69 :     Oid         opcintype = indexRel->rd_opcintype[ssup->ssup_attno - 1];
     193                 :     Oid         sortSupportFunction;
     194                 : 
     195              69 :     Assert(ssup->comparator == NULL);
     196                 : 
     197              69 :     if (indexRel->rd_rel->relam != GIST_AM_OID)
     198 UBC           0 :         elog(ERROR, "unexpected non-gist AM: %u", indexRel->rd_rel->relam);
     199 CBC          69 :     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              69 :     sortSupportFunction = get_opfamily_proc(opfamily, opcintype, opcintype,
     206                 :                                             GIST_SORTSUPPORT_PROC);
     207              69 :     if (!OidIsValid(sortSupportFunction))
     208 UBC           0 :         elog(ERROR, "missing support function %d(%u,%u) in opfamily %u",
     209                 :              GIST_SORTSUPPORT_PROC, opcintype, opcintype, opfamily);
     210 CBC          69 :     OidFunctionCall1(sortSupportFunction, PointerGetDatum(ssup));
     211              69 : }
        

Generated by: LCOV version v1.16-55-g56c0a2a