LCOV - code coverage report
Current view: top level - src/backend/access/nbtree - nbtcompare.c (source / functions) Hit Total Coverage
Test: PostgreSQL 13beta1 Lines: 129 139 92.8 %
Date: 2020-06-01 08:06:25 Functions: 20 21 95.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * nbtcompare.c
       4             :  *    Comparison functions for btree access method.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2020, 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   110959036 : btboolcmp(PG_FUNCTION_ARGS)
      74             : {
      75   110959036 :     bool        a = PG_GETARG_BOOL(0);
      76   110959036 :     bool        b = PG_GETARG_BOOL(1);
      77             : 
      78   110959036 :     PG_RETURN_INT32((int32) a - (int32) b);
      79             : }
      80             : 
      81             : Datum
      82     9306158 : btint2cmp(PG_FUNCTION_ARGS)
      83             : {
      84     9306158 :     int16       a = PG_GETARG_INT16(0);
      85     9306158 :     int16       b = PG_GETARG_INT16(1);
      86             : 
      87     9306158 :     PG_RETURN_INT32((int32) a - (int32) b);
      88             : }
      89             : 
      90             : static int
      91    66941098 : btint2fastcmp(Datum x, Datum y, SortSupport ssup)
      92             : {
      93    66941098 :     int16       a = DatumGetInt16(x);
      94    66941098 :     int16       b = DatumGetInt16(y);
      95             : 
      96    66941098 :     return (int) a - (int) b;
      97             : }
      98             : 
      99             : Datum
     100       15954 : btint2sortsupport(PG_FUNCTION_ARGS)
     101             : {
     102       15954 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     103             : 
     104       15954 :     ssup->comparator = btint2fastcmp;
     105       15954 :     PG_RETURN_VOID();
     106             : }
     107             : 
     108             : Datum
     109    59961150 : btint4cmp(PG_FUNCTION_ARGS)
     110             : {
     111    59961150 :     int32       a = PG_GETARG_INT32(0);
     112    59961150 :     int32       b = PG_GETARG_INT32(1);
     113             : 
     114    59961150 :     if (a > b)
     115    12453438 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     116    47507712 :     else if (a == b)
     117    31406772 :         PG_RETURN_INT32(0);
     118             :     else
     119    16100940 :         PG_RETURN_INT32(A_LESS_THAN_B);
     120             : }
     121             : 
     122             : static int
     123   238440748 : btint4fastcmp(Datum x, Datum y, SortSupport ssup)
     124             : {
     125   238440748 :     int32       a = DatumGetInt32(x);
     126   238440748 :     int32       b = DatumGetInt32(y);
     127             : 
     128   238440748 :     if (a > b)
     129    44617336 :         return A_GREATER_THAN_B;
     130   193823412 :     else if (a == b)
     131   144626050 :         return 0;
     132             :     else
     133    49197362 :         return A_LESS_THAN_B;
     134             : }
     135             : 
     136             : Datum
     137      144474 : btint4sortsupport(PG_FUNCTION_ARGS)
     138             : {
     139      144474 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     140             : 
     141      144474 :     ssup->comparator = btint4fastcmp;
     142      144474 :     PG_RETURN_VOID();
     143             : }
     144             : 
     145             : Datum
     146    15426394 : btint8cmp(PG_FUNCTION_ARGS)
     147             : {
     148    15426394 :     int64       a = PG_GETARG_INT64(0);
     149    15426394 :     int64       b = PG_GETARG_INT64(1);
     150             : 
     151    15426394 :     if (a > b)
     152     8676806 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     153     6749588 :     else if (a == b)
     154      837158 :         PG_RETURN_INT32(0);
     155             :     else
     156     5912430 :         PG_RETURN_INT32(A_LESS_THAN_B);
     157             : }
     158             : 
     159             : static int
     160     5921038 : btint8fastcmp(Datum x, Datum y, SortSupport ssup)
     161             : {
     162     5921038 :     int64       a = DatumGetInt64(x);
     163     5921038 :     int64       b = DatumGetInt64(y);
     164             : 
     165     5921038 :     if (a > b)
     166     1830902 :         return A_GREATER_THAN_B;
     167     4090136 :     else if (a == b)
     168      240618 :         return 0;
     169             :     else
     170     3849518 :         return A_LESS_THAN_B;
     171             : }
     172             : 
     173             : Datum
     174     1094416 : btint8sortsupport(PG_FUNCTION_ARGS)
     175             : {
     176     1094416 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     177             : 
     178     1094416 :     ssup->comparator = btint8fastcmp;
     179     1094416 :     PG_RETURN_VOID();
     180             : }
     181             : 
     182             : Datum
     183        1028 : btint48cmp(PG_FUNCTION_ARGS)
     184             : {
     185        1028 :     int32       a = PG_GETARG_INT32(0);
     186        1028 :     int64       b = PG_GETARG_INT64(1);
     187             : 
     188        1028 :     if (a > b)
     189         380 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     190         648 :     else if (a == b)
     191          64 :         PG_RETURN_INT32(0);
     192             :     else
     193         584 :         PG_RETURN_INT32(A_LESS_THAN_B);
     194             : }
     195             : 
     196             : Datum
     197          60 : btint84cmp(PG_FUNCTION_ARGS)
     198             : {
     199          60 :     int64       a = PG_GETARG_INT64(0);
     200          60 :     int32       b = PG_GETARG_INT32(1);
     201             : 
     202          60 :     if (a > b)
     203          20 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     204          40 :     else if (a == b)
     205          20 :         PG_RETURN_INT32(0);
     206             :     else
     207          20 :         PG_RETURN_INT32(A_LESS_THAN_B);
     208             : }
     209             : 
     210             : Datum
     211       12390 : btint24cmp(PG_FUNCTION_ARGS)
     212             : {
     213       12390 :     int16       a = PG_GETARG_INT16(0);
     214       12390 :     int32       b = PG_GETARG_INT32(1);
     215             : 
     216       12390 :     if (a > b)
     217        7344 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     218        5046 :     else if (a == b)
     219         102 :         PG_RETURN_INT32(0);
     220             :     else
     221        4944 :         PG_RETURN_INT32(A_LESS_THAN_B);
     222             : }
     223             : 
     224             : Datum
     225          24 : btint42cmp(PG_FUNCTION_ARGS)
     226             : {
     227          24 :     int32       a = PG_GETARG_INT32(0);
     228          24 :     int16       b = PG_GETARG_INT16(1);
     229             : 
     230          24 :     if (a > b)
     231           6 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     232          18 :     else if (a == b)
     233          12 :         PG_RETURN_INT32(0);
     234             :     else
     235           6 :         PG_RETURN_INT32(A_LESS_THAN_B);
     236             : }
     237             : 
     238             : Datum
     239          24 : btint28cmp(PG_FUNCTION_ARGS)
     240             : {
     241          24 :     int16       a = PG_GETARG_INT16(0);
     242          24 :     int64       b = PG_GETARG_INT64(1);
     243             : 
     244          24 :     if (a > b)
     245           0 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     246          24 :     else if (a == b)
     247           0 :         PG_RETURN_INT32(0);
     248             :     else
     249          24 :         PG_RETURN_INT32(A_LESS_THAN_B);
     250             : }
     251             : 
     252             : Datum
     253           0 : btint82cmp(PG_FUNCTION_ARGS)
     254             : {
     255           0 :     int64       a = PG_GETARG_INT64(0);
     256           0 :     int16       b = PG_GETARG_INT16(1);
     257             : 
     258           0 :     if (a > b)
     259           0 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     260           0 :     else if (a == b)
     261           0 :         PG_RETURN_INT32(0);
     262             :     else
     263           0 :         PG_RETURN_INT32(A_LESS_THAN_B);
     264             : }
     265             : 
     266             : Datum
     267   307700000 : btoidcmp(PG_FUNCTION_ARGS)
     268             : {
     269   307700000 :     Oid         a = PG_GETARG_OID(0);
     270   307700000 :     Oid         b = PG_GETARG_OID(1);
     271             : 
     272   307700000 :     if (a > b)
     273    62270162 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     274   245429838 :     else if (a == b)
     275   136396866 :         PG_RETURN_INT32(0);
     276             :     else
     277   109032972 :         PG_RETURN_INT32(A_LESS_THAN_B);
     278             : }
     279             : 
     280             : static int
     281   509777046 : btoidfastcmp(Datum x, Datum y, SortSupport ssup)
     282             : {
     283   509777046 :     Oid         a = DatumGetObjectId(x);
     284   509777046 :     Oid         b = DatumGetObjectId(y);
     285             : 
     286   509777046 :     if (a > b)
     287   122701060 :         return A_GREATER_THAN_B;
     288   387075986 :     else if (a == b)
     289   268176076 :         return 0;
     290             :     else
     291   118899910 :         return A_LESS_THAN_B;
     292             : }
     293             : 
     294             : Datum
     295      222026 : btoidsortsupport(PG_FUNCTION_ARGS)
     296             : {
     297      222026 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     298             : 
     299      222026 :     ssup->comparator = btoidfastcmp;
     300      222026 :     PG_RETURN_VOID();
     301             : }
     302             : 
     303             : Datum
     304    17491962 : btoidvectorcmp(PG_FUNCTION_ARGS)
     305             : {
     306    17491962 :     oidvector  *a = (oidvector *) PG_GETARG_POINTER(0);
     307    17491962 :     oidvector  *b = (oidvector *) PG_GETARG_POINTER(1);
     308             :     int         i;
     309             : 
     310             :     /* We arbitrarily choose to sort first by vector length */
     311    17491962 :     if (a->dim1 != b->dim1)
     312     2594396 :         PG_RETURN_INT32(a->dim1 - b->dim1);
     313             : 
     314    26086368 :     for (i = 0; i < a->dim1; i++)
     315             :     {
     316    20221140 :         if (a->values[i] != b->values[i])
     317             :         {
     318     9032338 :             if (a->values[i] > b->values[i])
     319     4827228 :                 PG_RETURN_INT32(A_GREATER_THAN_B);
     320             :             else
     321     4205110 :                 PG_RETURN_INT32(A_LESS_THAN_B);
     322             :         }
     323             :     }
     324     5865228 :     PG_RETURN_INT32(0);
     325             : }
     326             : 
     327             : Datum
     328   153371084 : btcharcmp(PG_FUNCTION_ARGS)
     329             : {
     330   153371084 :     char        a = PG_GETARG_CHAR(0);
     331   153371084 :     char        b = PG_GETARG_CHAR(1);
     332             : 
     333             :     /* Be careful to compare chars as unsigned */
     334   153371084 :     PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
     335             : }

Generated by: LCOV version 1.13