LCOV - differential code coverage report
Current view: top level - src/backend/access/nbtree - nbtcompare.c (source / functions) Coverage Total Hit UBC CBC
Current: Differential Code Coverage HEAD vs 15 Lines: 91.9 % 123 113 10 113
Current Date: 2023-04-08 15:15:32 Functions: 94.7 % 19 18 1 18
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  Line data    Source code
       1                 : /*-------------------------------------------------------------------------
       2                 :  *
       3                 :  * nbtcompare.c
       4                 :  *    Comparison functions for btree access method.
       5                 :  *
       6                 :  * Portions Copyright (c) 1996-2023, PostgreSQL Global Development Group
       7                 :  * Portions Copyright (c) 1994, Regents of the University of California
       8                 :  *
       9                 :  *
      10                 :  * IDENTIFICATION
      11                 :  *    src/backend/access/nbtree/nbtcompare.c
      12                 :  *
      13                 :  * NOTES
      14                 :  *
      15                 :  *  These functions are stored in pg_amproc.  For each operator class
      16                 :  *  defined on btrees, they compute
      17                 :  *
      18                 :  *              compare(a, b):
      19                 :  *                      < 0 if a < b,
      20                 :  *                      = 0 if a == b,
      21                 :  *                      > 0 if a > b.
      22                 :  *
      23                 :  *  The result is always an int32 regardless of the input datatype.
      24                 :  *
      25                 :  *  Although any negative int32 is acceptable for reporting "<",
      26                 :  *  and any positive int32 is acceptable for reporting ">", routines
      27                 :  *  that work on 32-bit or wider datatypes can't just return "a - b".
      28                 :  *  That could overflow and give the wrong answer.
      29                 :  *
      30                 :  *  NOTE: it is critical that the comparison function impose a total order
      31                 :  *  on all non-NULL values of the data type, and that the datatype's
      32                 :  *  boolean comparison operators (= < >= etc) yield results consistent
      33                 :  *  with the comparison routine.  Otherwise bad behavior may ensue.
      34                 :  *  (For example, the comparison operators must NOT punt when faced with
      35                 :  *  NAN or other funny values; you must devise some collation sequence for
      36                 :  *  all such values.)  If the datatype is not trivial, this is most
      37                 :  *  reliably done by having the boolean operators invoke the same
      38                 :  *  three-way comparison code that the btree function does.  Therefore,
      39                 :  *  this file contains only btree support for "trivial" datatypes ---
      40                 :  *  all others are in the /utils/adt/ files that implement their datatypes.
      41                 :  *
      42                 :  *  NOTE: these routines must not leak memory, since memory allocated
      43                 :  *  during an index access won't be recovered till end of query.  This
      44                 :  *  primarily affects comparison routines for toastable datatypes;
      45                 :  *  they have to be careful to free any detoasted copy of an input datum.
      46                 :  *
      47                 :  *  NOTE: we used to forbid comparison functions from returning INT_MIN,
      48                 :  *  but that proves to be too error-prone because some platforms' versions
      49                 :  *  of memcmp() etc can return INT_MIN.  As a means of stress-testing
      50                 :  *  callers, this file can be compiled with STRESS_SORT_INT_MIN defined
      51                 :  *  to cause many of these functions to return INT_MIN or INT_MAX instead of
      52                 :  *  their customary -1/+1.  For production, though, that's not a good idea
      53                 :  *  since users or third-party code might expect the traditional results.
      54                 :  *-------------------------------------------------------------------------
      55                 :  */
      56                 : #include "postgres.h"
      57                 : 
      58                 : #include <limits.h>
      59                 : 
      60                 : #include "utils/builtins.h"
      61                 : #include "utils/sortsupport.h"
      62                 : 
      63                 : #ifdef STRESS_SORT_INT_MIN
      64                 : #define A_LESS_THAN_B       INT_MIN
      65                 : #define A_GREATER_THAN_B    INT_MAX
      66                 : #else
      67                 : #define A_LESS_THAN_B       (-1)
      68                 : #define A_GREATER_THAN_B    1
      69                 : #endif
      70                 : 
      71                 : 
      72                 : Datum
      73 CBC    92359605 : btboolcmp(PG_FUNCTION_ARGS)
      74                 : {
      75        92359605 :     bool        a = PG_GETARG_BOOL(0);
      76        92359605 :     bool        b = PG_GETARG_BOOL(1);
      77                 : 
      78        92359605 :     PG_RETURN_INT32((int32) a - (int32) b);
      79                 : }
      80                 : 
      81                 : Datum
      82         8321455 : btint2cmp(PG_FUNCTION_ARGS)
      83                 : {
      84         8321455 :     int16       a = PG_GETARG_INT16(0);
      85         8321455 :     int16       b = PG_GETARG_INT16(1);
      86                 : 
      87         8321455 :     PG_RETURN_INT32((int32) a - (int32) b);
      88                 : }
      89                 : 
      90                 : static int
      91        81347810 : btint2fastcmp(Datum x, Datum y, SortSupport ssup)
      92                 : {
      93        81347810 :     int16       a = DatumGetInt16(x);
      94        81347810 :     int16       b = DatumGetInt16(y);
      95                 : 
      96        81347810 :     return (int) a - (int) b;
      97                 : }
      98                 : 
      99                 : Datum
     100            9270 : btint2sortsupport(PG_FUNCTION_ARGS)
     101                 : {
     102            9270 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     103                 : 
     104            9270 :     ssup->comparator = btint2fastcmp;
     105            9270 :     PG_RETURN_VOID();
     106                 : }
     107                 : 
     108                 : Datum
     109        47213355 : btint4cmp(PG_FUNCTION_ARGS)
     110                 : {
     111        47213355 :     int32       a = PG_GETARG_INT32(0);
     112        47213355 :     int32       b = PG_GETARG_INT32(1);
     113                 : 
     114        47213355 :     if (a > b)
     115        17169383 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     116        30043972 :     else if (a == b)
     117        10833823 :         PG_RETURN_INT32(0);
     118                 :     else
     119        19210149 :         PG_RETURN_INT32(A_LESS_THAN_B);
     120                 : }
     121                 : 
     122                 : Datum
     123          103323 : btint4sortsupport(PG_FUNCTION_ARGS)
     124                 : {
     125          103323 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     126                 : 
     127          103323 :     ssup->comparator = ssup_datum_int32_cmp;
     128          103323 :     PG_RETURN_VOID();
     129                 : }
     130                 : 
     131                 : Datum
     132         7801644 : btint8cmp(PG_FUNCTION_ARGS)
     133                 : {
     134         7801644 :     int64       a = PG_GETARG_INT64(0);
     135         7801644 :     int64       b = PG_GETARG_INT64(1);
     136                 : 
     137         7801644 :     if (a > b)
     138         4355459 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     139         3446185 :     else if (a == b)
     140          420127 :         PG_RETURN_INT32(0);
     141                 :     else
     142         3026058 :         PG_RETURN_INT32(A_LESS_THAN_B);
     143                 : }
     144                 : 
     145                 : #if SIZEOF_DATUM < 8
     146                 : static int
     147                 : btint8fastcmp(Datum x, Datum y, SortSupport ssup)
     148                 : {
     149                 :     int64       a = DatumGetInt64(x);
     150                 :     int64       b = DatumGetInt64(y);
     151                 : 
     152                 :     if (a > b)
     153                 :         return A_GREATER_THAN_B;
     154                 :     else if (a == b)
     155                 :         return 0;
     156                 :     else
     157                 :         return A_LESS_THAN_B;
     158                 : }
     159                 : #endif
     160                 : 
     161                 : Datum
     162            1422 : btint8sortsupport(PG_FUNCTION_ARGS)
     163                 : {
     164            1422 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     165                 : 
     166                 : #if SIZEOF_DATUM >= 8
     167            1422 :     ssup->comparator = ssup_datum_signed_cmp;
     168                 : #else
     169                 :     ssup->comparator = btint8fastcmp;
     170                 : #endif
     171            1422 :     PG_RETURN_VOID();
     172                 : }
     173                 : 
     174                 : Datum
     175             717 : btint48cmp(PG_FUNCTION_ARGS)
     176                 : {
     177             717 :     int32       a = PG_GETARG_INT32(0);
     178             717 :     int64       b = PG_GETARG_INT64(1);
     179                 : 
     180             717 :     if (a > b)
     181             249 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     182             468 :     else if (a == b)
     183              33 :         PG_RETURN_INT32(0);
     184                 :     else
     185             435 :         PG_RETURN_INT32(A_LESS_THAN_B);
     186                 : }
     187                 : 
     188                 : Datum
     189              45 : btint84cmp(PG_FUNCTION_ARGS)
     190                 : {
     191              45 :     int64       a = PG_GETARG_INT64(0);
     192              45 :     int32       b = PG_GETARG_INT32(1);
     193                 : 
     194              45 :     if (a > b)
     195              15 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     196              30 :     else if (a == b)
     197              15 :         PG_RETURN_INT32(0);
     198                 :     else
     199              15 :         PG_RETURN_INT32(A_LESS_THAN_B);
     200                 : }
     201                 : 
     202                 : Datum
     203           16437 : btint24cmp(PG_FUNCTION_ARGS)
     204                 : {
     205           16437 :     int16       a = PG_GETARG_INT16(0);
     206           16437 :     int32       b = PG_GETARG_INT32(1);
     207                 : 
     208           16437 :     if (a > b)
     209            9536 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     210            6901 :     else if (a == b)
     211            1748 :         PG_RETURN_INT32(0);
     212                 :     else
     213            5153 :         PG_RETURN_INT32(A_LESS_THAN_B);
     214                 : }
     215                 : 
     216                 : Datum
     217             627 : btint42cmp(PG_FUNCTION_ARGS)
     218                 : {
     219             627 :     int32       a = PG_GETARG_INT32(0);
     220             627 :     int16       b = PG_GETARG_INT16(1);
     221                 : 
     222             627 :     if (a > b)
     223              36 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     224             591 :     else if (a == b)
     225             127 :         PG_RETURN_INT32(0);
     226                 :     else
     227             464 :         PG_RETURN_INT32(A_LESS_THAN_B);
     228                 : }
     229                 : 
     230                 : Datum
     231              18 : btint28cmp(PG_FUNCTION_ARGS)
     232                 : {
     233              18 :     int16       a = PG_GETARG_INT16(0);
     234              18 :     int64       b = PG_GETARG_INT64(1);
     235                 : 
     236              18 :     if (a > b)
     237 UBC           0 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     238 CBC          18 :     else if (a == b)
     239 UBC           0 :         PG_RETURN_INT32(0);
     240                 :     else
     241 CBC          18 :         PG_RETURN_INT32(A_LESS_THAN_B);
     242                 : }
     243                 : 
     244                 : Datum
     245 UBC           0 : btint82cmp(PG_FUNCTION_ARGS)
     246                 : {
     247               0 :     int64       a = PG_GETARG_INT64(0);
     248               0 :     int16       b = PG_GETARG_INT16(1);
     249                 : 
     250               0 :     if (a > b)
     251               0 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     252               0 :     else if (a == b)
     253               0 :         PG_RETURN_INT32(0);
     254                 :     else
     255               0 :         PG_RETURN_INT32(A_LESS_THAN_B);
     256                 : }
     257                 : 
     258                 : Datum
     259 CBC   143511100 : btoidcmp(PG_FUNCTION_ARGS)
     260                 : {
     261       143511100 :     Oid         a = PG_GETARG_OID(0);
     262       143511100 :     Oid         b = PG_GETARG_OID(1);
     263                 : 
     264       143511100 :     if (a > b)
     265        32440154 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     266       111070946 :     else if (a == b)
     267        36247307 :         PG_RETURN_INT32(0);
     268                 :     else
     269        74823639 :         PG_RETURN_INT32(A_LESS_THAN_B);
     270                 : }
     271                 : 
     272                 : static int
     273       362043838 : btoidfastcmp(Datum x, Datum y, SortSupport ssup)
     274                 : {
     275       362043838 :     Oid         a = DatumGetObjectId(x);
     276       362043838 :     Oid         b = DatumGetObjectId(y);
     277                 : 
     278       362043838 :     if (a > b)
     279        89397142 :         return A_GREATER_THAN_B;
     280       272646696 :     else if (a == b)
     281       183443992 :         return 0;
     282                 :     else
     283        89202704 :         return A_LESS_THAN_B;
     284                 : }
     285                 : 
     286                 : Datum
     287          179850 : btoidsortsupport(PG_FUNCTION_ARGS)
     288                 : {
     289          179850 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     290                 : 
     291          179850 :     ssup->comparator = btoidfastcmp;
     292          179850 :     PG_RETURN_VOID();
     293                 : }
     294                 : 
     295                 : Datum
     296        14546183 : btoidvectorcmp(PG_FUNCTION_ARGS)
     297                 : {
     298        14546183 :     oidvector  *a = (oidvector *) PG_GETARG_POINTER(0);
     299        14546183 :     oidvector  *b = (oidvector *) PG_GETARG_POINTER(1);
     300                 :     int         i;
     301                 : 
     302                 :     /* We arbitrarily choose to sort first by vector length */
     303        14546183 :     if (a->dim1 != b->dim1)
     304         2425930 :         PG_RETURN_INT32(a->dim1 - b->dim1);
     305                 : 
     306        21431084 :     for (i = 0; i < a->dim1; i++)
     307                 :     {
     308        16479988 :         if (a->values[i] != b->values[i])
     309                 :         {
     310         7169157 :             if (a->values[i] > b->values[i])
     311         3822871 :                 PG_RETURN_INT32(A_GREATER_THAN_B);
     312                 :             else
     313         3346286 :                 PG_RETURN_INT32(A_LESS_THAN_B);
     314                 :         }
     315                 :     }
     316         4951096 :     PG_RETURN_INT32(0);
     317                 : }
     318                 : 
     319                 : Datum
     320       105151804 : btcharcmp(PG_FUNCTION_ARGS)
     321                 : {
     322       105151804 :     char        a = PG_GETARG_CHAR(0);
     323       105151804 :     char        b = PG_GETARG_CHAR(1);
     324                 : 
     325                 :     /* Be careful to compare chars as unsigned */
     326       105151804 :     PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
     327                 : }
        

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