LCOV - code coverage report
Current view: top level - src/backend/access/nbtree - nbtcompare.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 64.0 % 292 187
Test Date: 2026-03-27 22:16:19 Functions: 67.4 % 43 29
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-2026, 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/fmgrprotos.h"
      62              : #include "utils/skipsupport.h"
      63              : #include "utils/sortsupport.h"
      64              : 
      65              : #ifdef STRESS_SORT_INT_MIN
      66              : #define A_LESS_THAN_B       INT_MIN
      67              : #define A_GREATER_THAN_B    INT_MAX
      68              : #else
      69              : #define A_LESS_THAN_B       (-1)
      70              : #define A_GREATER_THAN_B    1
      71              : #endif
      72              : 
      73              : 
      74              : Datum
      75     35409925 : btboolcmp(PG_FUNCTION_ARGS)
      76              : {
      77     35409925 :     bool        a = PG_GETARG_BOOL(0);
      78     35409925 :     bool        b = PG_GETARG_BOOL(1);
      79              : 
      80     35409925 :     PG_RETURN_INT32((int32) a - (int32) b);
      81              : }
      82              : 
      83              : static Datum
      84            0 : bool_decrement(Relation rel, Datum existing, bool *underflow)
      85              : {
      86            0 :     bool        bexisting = DatumGetBool(existing);
      87              : 
      88            0 :     if (bexisting == false)
      89              :     {
      90              :         /* return value is undefined */
      91            0 :         *underflow = true;
      92            0 :         return (Datum) 0;
      93              :     }
      94              : 
      95            0 :     *underflow = false;
      96            0 :     return BoolGetDatum(bexisting - 1);
      97              : }
      98              : 
      99              : static Datum
     100            0 : bool_increment(Relation rel, Datum existing, bool *overflow)
     101              : {
     102            0 :     bool        bexisting = DatumGetBool(existing);
     103              : 
     104            0 :     if (bexisting == true)
     105              :     {
     106              :         /* return value is undefined */
     107            0 :         *overflow = true;
     108            0 :         return (Datum) 0;
     109              :     }
     110              : 
     111            0 :     *overflow = false;
     112            0 :     return BoolGetDatum(bexisting + 1);
     113              : }
     114              : 
     115              : Datum
     116            0 : btboolskipsupport(PG_FUNCTION_ARGS)
     117              : {
     118            0 :     SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0);
     119              : 
     120            0 :     sksup->decrement = bool_decrement;
     121            0 :     sksup->increment = bool_increment;
     122            0 :     sksup->low_elem = BoolGetDatum(false);
     123            0 :     sksup->high_elem = BoolGetDatum(true);
     124              : 
     125            0 :     PG_RETURN_VOID();
     126              : }
     127              : 
     128              : Datum
     129      8754461 : btint2cmp(PG_FUNCTION_ARGS)
     130              : {
     131      8754461 :     int16       a = PG_GETARG_INT16(0);
     132      8754461 :     int16       b = PG_GETARG_INT16(1);
     133              : 
     134      8754461 :     PG_RETURN_INT32((int32) a - (int32) b);
     135              : }
     136              : 
     137              : static int
     138     25983456 : btint2fastcmp(Datum x, Datum y, SortSupport ssup)
     139              : {
     140     25983456 :     int16       a = DatumGetInt16(x);
     141     25983456 :     int16       b = DatumGetInt16(y);
     142              : 
     143     25983456 :     return (int) a - (int) b;
     144              : }
     145              : 
     146              : Datum
     147         6298 : btint2sortsupport(PG_FUNCTION_ARGS)
     148              : {
     149         6298 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     150              : 
     151         6298 :     ssup->comparator = btint2fastcmp;
     152         6298 :     PG_RETURN_VOID();
     153              : }
     154              : 
     155              : static Datum
     156            0 : int2_decrement(Relation rel, Datum existing, bool *underflow)
     157              : {
     158            0 :     int16       iexisting = DatumGetInt16(existing);
     159              : 
     160            0 :     if (iexisting == PG_INT16_MIN)
     161              :     {
     162              :         /* return value is undefined */
     163            0 :         *underflow = true;
     164            0 :         return (Datum) 0;
     165              :     }
     166              : 
     167            0 :     *underflow = false;
     168            0 :     return Int16GetDatum(iexisting - 1);
     169              : }
     170              : 
     171              : static Datum
     172            2 : int2_increment(Relation rel, Datum existing, bool *overflow)
     173              : {
     174            2 :     int16       iexisting = DatumGetInt16(existing);
     175              : 
     176            2 :     if (iexisting == PG_INT16_MAX)
     177              :     {
     178              :         /* return value is undefined */
     179            0 :         *overflow = true;
     180            0 :         return (Datum) 0;
     181              :     }
     182              : 
     183            2 :     *overflow = false;
     184            2 :     return Int16GetDatum(iexisting + 1);
     185              : }
     186              : 
     187              : Datum
     188          121 : btint2skipsupport(PG_FUNCTION_ARGS)
     189              : {
     190          121 :     SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0);
     191              : 
     192          121 :     sksup->decrement = int2_decrement;
     193          121 :     sksup->increment = int2_increment;
     194          121 :     sksup->low_elem = Int16GetDatum(PG_INT16_MIN);
     195          121 :     sksup->high_elem = Int16GetDatum(PG_INT16_MAX);
     196              : 
     197          121 :     PG_RETURN_VOID();
     198              : }
     199              : 
     200              : Datum
     201     66654357 : btint4cmp(PG_FUNCTION_ARGS)
     202              : {
     203     66654357 :     int32       a = PG_GETARG_INT32(0);
     204     66654357 :     int32       b = PG_GETARG_INT32(1);
     205              : 
     206     66654357 :     if (a > b)
     207     24208142 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     208     42446215 :     else if (a == b)
     209     13290786 :         PG_RETURN_INT32(0);
     210              :     else
     211     29155429 :         PG_RETURN_INT32(A_LESS_THAN_B);
     212              : }
     213              : 
     214              : Datum
     215       114241 : btint4sortsupport(PG_FUNCTION_ARGS)
     216              : {
     217       114241 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     218              : 
     219       114241 :     ssup->comparator = ssup_datum_int32_cmp;
     220       114241 :     PG_RETURN_VOID();
     221              : }
     222              : 
     223              : static Datum
     224         2644 : int4_decrement(Relation rel, Datum existing, bool *underflow)
     225              : {
     226         2644 :     int32       iexisting = DatumGetInt32(existing);
     227              : 
     228         2644 :     if (iexisting == PG_INT32_MIN)
     229              :     {
     230              :         /* return value is undefined */
     231            0 :         *underflow = true;
     232            0 :         return (Datum) 0;
     233              :     }
     234              : 
     235         2644 :     *underflow = false;
     236         2644 :     return Int32GetDatum(iexisting - 1);
     237              : }
     238              : 
     239              : static Datum
     240         2608 : int4_increment(Relation rel, Datum existing, bool *overflow)
     241              : {
     242         2608 :     int32       iexisting = DatumGetInt32(existing);
     243              : 
     244         2608 :     if (iexisting == PG_INT32_MAX)
     245              :     {
     246              :         /* return value is undefined */
     247           20 :         *overflow = true;
     248           20 :         return (Datum) 0;
     249              :     }
     250              : 
     251         2588 :     *overflow = false;
     252         2588 :     return Int32GetDatum(iexisting + 1);
     253              : }
     254              : 
     255              : Datum
     256          202 : btint4skipsupport(PG_FUNCTION_ARGS)
     257              : {
     258          202 :     SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0);
     259              : 
     260          202 :     sksup->decrement = int4_decrement;
     261          202 :     sksup->increment = int4_increment;
     262          202 :     sksup->low_elem = Int32GetDatum(PG_INT32_MIN);
     263          202 :     sksup->high_elem = Int32GetDatum(PG_INT32_MAX);
     264              : 
     265          202 :     PG_RETURN_VOID();
     266              : }
     267              : 
     268              : Datum
     269      8351561 : btint8cmp(PG_FUNCTION_ARGS)
     270              : {
     271      8351561 :     int64       a = PG_GETARG_INT64(0);
     272      8351561 :     int64       b = PG_GETARG_INT64(1);
     273              : 
     274      8351561 :     if (a > b)
     275      4868721 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     276      3482840 :     else if (a == b)
     277       423830 :         PG_RETURN_INT32(0);
     278              :     else
     279      3059010 :         PG_RETURN_INT32(A_LESS_THAN_B);
     280              : }
     281              : 
     282              : Datum
     283         2254 : btint8sortsupport(PG_FUNCTION_ARGS)
     284              : {
     285         2254 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     286              : 
     287         2254 :     ssup->comparator = ssup_datum_signed_cmp;
     288         2254 :     PG_RETURN_VOID();
     289              : }
     290              : 
     291              : static Datum
     292            0 : int8_decrement(Relation rel, Datum existing, bool *underflow)
     293              : {
     294            0 :     int64       iexisting = DatumGetInt64(existing);
     295              : 
     296            0 :     if (iexisting == PG_INT64_MIN)
     297              :     {
     298              :         /* return value is undefined */
     299            0 :         *underflow = true;
     300            0 :         return (Datum) 0;
     301              :     }
     302              : 
     303            0 :     *underflow = false;
     304            0 :     return Int64GetDatum(iexisting - 1);
     305              : }
     306              : 
     307              : static Datum
     308            0 : int8_increment(Relation rel, Datum existing, bool *overflow)
     309              : {
     310            0 :     int64       iexisting = DatumGetInt64(existing);
     311              : 
     312            0 :     if (iexisting == PG_INT64_MAX)
     313              :     {
     314              :         /* return value is undefined */
     315            0 :         *overflow = true;
     316            0 :         return (Datum) 0;
     317              :     }
     318              : 
     319            0 :     *overflow = false;
     320            0 :     return Int64GetDatum(iexisting + 1);
     321              : }
     322              : 
     323              : Datum
     324            0 : btint8skipsupport(PG_FUNCTION_ARGS)
     325              : {
     326            0 :     SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0);
     327              : 
     328            0 :     sksup->decrement = int8_decrement;
     329            0 :     sksup->increment = int8_increment;
     330            0 :     sksup->low_elem = Int64GetDatum(PG_INT64_MIN);
     331            0 :     sksup->high_elem = Int64GetDatum(PG_INT64_MAX);
     332              : 
     333            0 :     PG_RETURN_VOID();
     334              : }
     335              : 
     336              : Datum
     337          987 : btint48cmp(PG_FUNCTION_ARGS)
     338              : {
     339          987 :     int32       a = PG_GETARG_INT32(0);
     340          987 :     int64       b = PG_GETARG_INT64(1);
     341              : 
     342          987 :     if (a > b)
     343          339 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     344          648 :     else if (a == b)
     345           50 :         PG_RETURN_INT32(0);
     346              :     else
     347          598 :         PG_RETURN_INT32(A_LESS_THAN_B);
     348              : }
     349              : 
     350              : Datum
     351          162 : btint84cmp(PG_FUNCTION_ARGS)
     352              : {
     353          162 :     int64       a = PG_GETARG_INT64(0);
     354          162 :     int32       b = PG_GETARG_INT32(1);
     355              : 
     356          162 :     if (a > b)
     357           58 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     358          104 :     else if (a == b)
     359           42 :         PG_RETURN_INT32(0);
     360              :     else
     361           62 :         PG_RETURN_INT32(A_LESS_THAN_B);
     362              : }
     363              : 
     364              : Datum
     365        36817 : btint24cmp(PG_FUNCTION_ARGS)
     366              : {
     367        36817 :     int16       a = PG_GETARG_INT16(0);
     368        36817 :     int32       b = PG_GETARG_INT32(1);
     369              : 
     370        36817 :     if (a > b)
     371        19929 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     372        16888 :     else if (a == b)
     373         5649 :         PG_RETURN_INT32(0);
     374              :     else
     375        11239 :         PG_RETURN_INT32(A_LESS_THAN_B);
     376              : }
     377              : 
     378              : Datum
     379          994 : btint42cmp(PG_FUNCTION_ARGS)
     380              : {
     381          994 :     int32       a = PG_GETARG_INT32(0);
     382          994 :     int16       b = PG_GETARG_INT16(1);
     383              : 
     384          994 :     if (a > b)
     385           78 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     386          916 :     else if (a == b)
     387          213 :         PG_RETURN_INT32(0);
     388              :     else
     389          703 :         PG_RETURN_INT32(A_LESS_THAN_B);
     390              : }
     391              : 
     392              : Datum
     393           47 : btint28cmp(PG_FUNCTION_ARGS)
     394              : {
     395           47 :     int16       a = PG_GETARG_INT16(0);
     396           47 :     int64       b = PG_GETARG_INT64(1);
     397              : 
     398           47 :     if (a > b)
     399            6 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     400           41 :     else if (a == b)
     401            5 :         PG_RETURN_INT32(0);
     402              :     else
     403           36 :         PG_RETURN_INT32(A_LESS_THAN_B);
     404              : }
     405              : 
     406              : Datum
     407           17 : btint82cmp(PG_FUNCTION_ARGS)
     408              : {
     409           17 :     int64       a = PG_GETARG_INT64(0);
     410           17 :     int16       b = PG_GETARG_INT16(1);
     411              : 
     412           17 :     if (a > b)
     413            6 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     414           11 :     else if (a == b)
     415            5 :         PG_RETURN_INT32(0);
     416              :     else
     417            6 :         PG_RETURN_INT32(A_LESS_THAN_B);
     418              : }
     419              : 
     420              : Datum
     421    143719878 : btoidcmp(PG_FUNCTION_ARGS)
     422              : {
     423    143719878 :     Oid         a = PG_GETARG_OID(0);
     424    143719878 :     Oid         b = PG_GETARG_OID(1);
     425              : 
     426    143719878 :     if (a > b)
     427     39586724 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     428    104133154 :     else if (a == b)
     429     33925659 :         PG_RETURN_INT32(0);
     430              :     else
     431     70207495 :         PG_RETURN_INT32(A_LESS_THAN_B);
     432              : }
     433              : 
     434              : static int
     435    154013914 : btoidfastcmp(Datum x, Datum y, SortSupport ssup)
     436              : {
     437    154013914 :     Oid         a = DatumGetObjectId(x);
     438    154013914 :     Oid         b = DatumGetObjectId(y);
     439              : 
     440    154013914 :     if (a > b)
     441     38084176 :         return A_GREATER_THAN_B;
     442    115929738 :     else if (a == b)
     443     78321153 :         return 0;
     444              :     else
     445     37608585 :         return A_LESS_THAN_B;
     446              : }
     447              : 
     448              : Datum
     449        70743 : btoidsortsupport(PG_FUNCTION_ARGS)
     450              : {
     451        70743 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     452              : 
     453        70743 :     ssup->comparator = btoidfastcmp;
     454        70743 :     PG_RETURN_VOID();
     455              : }
     456              : 
     457              : static Datum
     458            0 : oid_decrement(Relation rel, Datum existing, bool *underflow)
     459              : {
     460            0 :     Oid         oexisting = DatumGetObjectId(existing);
     461              : 
     462            0 :     if (oexisting == InvalidOid)
     463              :     {
     464              :         /* return value is undefined */
     465            0 :         *underflow = true;
     466            0 :         return (Datum) 0;
     467              :     }
     468              : 
     469            0 :     *underflow = false;
     470            0 :     return ObjectIdGetDatum(oexisting - 1);
     471              : }
     472              : 
     473              : static Datum
     474          874 : oid_increment(Relation rel, Datum existing, bool *overflow)
     475              : {
     476          874 :     Oid         oexisting = DatumGetObjectId(existing);
     477              : 
     478          874 :     if (oexisting == OID_MAX)
     479              :     {
     480              :         /* return value is undefined */
     481            0 :         *overflow = true;
     482            0 :         return (Datum) 0;
     483              :     }
     484              : 
     485          874 :     *overflow = false;
     486          874 :     return ObjectIdGetDatum(oexisting + 1);
     487              : }
     488              : 
     489              : Datum
     490         1933 : btoidskipsupport(PG_FUNCTION_ARGS)
     491              : {
     492         1933 :     SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0);
     493              : 
     494         1933 :     sksup->decrement = oid_decrement;
     495         1933 :     sksup->increment = oid_increment;
     496         1933 :     sksup->low_elem = ObjectIdGetDatum(InvalidOid);
     497         1933 :     sksup->high_elem = ObjectIdGetDatum(OID_MAX);
     498              : 
     499         1933 :     PG_RETURN_VOID();
     500              : }
     501              : 
     502              : Datum
     503           15 : btoid8cmp(PG_FUNCTION_ARGS)
     504              : {
     505           15 :     Oid8        a = PG_GETARG_OID8(0);
     506           15 :     Oid8        b = PG_GETARG_OID8(1);
     507              : 
     508           15 :     if (a > b)
     509            5 :         PG_RETURN_INT32(A_GREATER_THAN_B);
     510           10 :     else if (a == b)
     511            5 :         PG_RETURN_INT32(0);
     512              :     else
     513            5 :         PG_RETURN_INT32(A_LESS_THAN_B);
     514              : }
     515              : 
     516              : static int
     517         2916 : btoid8fastcmp(Datum x, Datum y, SortSupport ssup)
     518              : {
     519         2916 :     Oid8        a = DatumGetObjectId8(x);
     520         2916 :     Oid8        b = DatumGetObjectId8(y);
     521              : 
     522         2916 :     if (a > b)
     523         1756 :         return A_GREATER_THAN_B;
     524         1160 :     else if (a == b)
     525            0 :         return 0;
     526              :     else
     527         1160 :         return A_LESS_THAN_B;
     528              : }
     529              : 
     530              : Datum
     531            8 : btoid8sortsupport(PG_FUNCTION_ARGS)
     532              : {
     533            8 :     SortSupport ssup = (SortSupport) PG_GETARG_POINTER(0);
     534              : 
     535            8 :     ssup->comparator = btoid8fastcmp;
     536            8 :     PG_RETURN_VOID();
     537              : }
     538              : 
     539              : static Datum
     540            0 : oid8_decrement(Relation rel, Datum existing, bool *underflow)
     541              : {
     542            0 :     Oid8        oexisting = DatumGetObjectId8(existing);
     543              : 
     544            0 :     if (oexisting == InvalidOid8)
     545              :     {
     546              :         /* return value is undefined */
     547            0 :         *underflow = true;
     548            0 :         return (Datum) 0;
     549              :     }
     550              : 
     551            0 :     *underflow = false;
     552            0 :     return ObjectId8GetDatum(oexisting - 1);
     553              : }
     554              : 
     555              : static Datum
     556            0 : oid8_increment(Relation rel, Datum existing, bool *overflow)
     557              : {
     558            0 :     Oid8        oexisting = DatumGetObjectId8(existing);
     559              : 
     560            0 :     if (oexisting == OID8_MAX)
     561              :     {
     562              :         /* return value is undefined */
     563            0 :         *overflow = true;
     564            0 :         return (Datum) 0;
     565              :     }
     566              : 
     567            0 :     *overflow = false;
     568            0 :     return ObjectId8GetDatum(oexisting + 1);
     569              : }
     570              : 
     571              : Datum
     572            0 : btoid8skipsupport(PG_FUNCTION_ARGS)
     573              : {
     574            0 :     SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0);
     575              : 
     576            0 :     sksup->decrement = oid8_decrement;
     577            0 :     sksup->increment = oid8_increment;
     578            0 :     sksup->low_elem = ObjectId8GetDatum(InvalidOid8);
     579            0 :     sksup->high_elem = ObjectId8GetDatum(OID8_MAX);
     580              : 
     581            0 :     PG_RETURN_VOID();
     582              : }
     583              : 
     584              : Datum
     585      4319760 : btoidvectorcmp(PG_FUNCTION_ARGS)
     586              : {
     587      4319760 :     oidvector  *a = (oidvector *) PG_GETARG_POINTER(0);
     588      4319760 :     oidvector  *b = (oidvector *) PG_GETARG_POINTER(1);
     589              :     int         i;
     590              : 
     591      4319760 :     check_valid_oidvector(a);
     592      4319760 :     check_valid_oidvector(b);
     593              : 
     594              :     /* We arbitrarily choose to sort first by vector length */
     595      4319760 :     if (a->dim1 != b->dim1)
     596       705377 :         PG_RETURN_INT32(a->dim1 - b->dim1);
     597              : 
     598      6249966 :     for (i = 0; i < a->dim1; i++)
     599              :     {
     600      4765881 :         if (a->values[i] != b->values[i])
     601              :         {
     602      2130298 :             if (a->values[i] > b->values[i])
     603      1114605 :                 PG_RETURN_INT32(A_GREATER_THAN_B);
     604              :             else
     605      1015693 :                 PG_RETURN_INT32(A_LESS_THAN_B);
     606              :         }
     607              :     }
     608      1484085 :     PG_RETURN_INT32(0);
     609              : }
     610              : 
     611              : Datum
     612     35213195 : btcharcmp(PG_FUNCTION_ARGS)
     613              : {
     614     35213195 :     char        a = PG_GETARG_CHAR(0);
     615     35213195 :     char        b = PG_GETARG_CHAR(1);
     616              : 
     617              :     /* Be careful to compare chars as unsigned */
     618     35213195 :     PG_RETURN_INT32((int32) ((uint8) a) - (int32) ((uint8) b));
     619              : }
     620              : 
     621              : static Datum
     622            0 : char_decrement(Relation rel, Datum existing, bool *underflow)
     623              : {
     624            0 :     uint8       cexisting = DatumGetUInt8(existing);
     625              : 
     626            0 :     if (cexisting == 0)
     627              :     {
     628              :         /* return value is undefined */
     629            0 :         *underflow = true;
     630            0 :         return (Datum) 0;
     631              :     }
     632              : 
     633            0 :     *underflow = false;
     634            0 :     return CharGetDatum((uint8) cexisting - 1);
     635              : }
     636              : 
     637              : static Datum
     638            0 : char_increment(Relation rel, Datum existing, bool *overflow)
     639              : {
     640            0 :     uint8       cexisting = DatumGetUInt8(existing);
     641              : 
     642            0 :     if (cexisting == UCHAR_MAX)
     643              :     {
     644              :         /* return value is undefined */
     645            0 :         *overflow = true;
     646            0 :         return (Datum) 0;
     647              :     }
     648              : 
     649            0 :     *overflow = false;
     650            0 :     return CharGetDatum((uint8) cexisting + 1);
     651              : }
     652              : 
     653              : Datum
     654            0 : btcharskipsupport(PG_FUNCTION_ARGS)
     655              : {
     656            0 :     SkipSupport sksup = (SkipSupport) PG_GETARG_POINTER(0);
     657              : 
     658            0 :     sksup->decrement = char_decrement;
     659            0 :     sksup->increment = char_increment;
     660              : 
     661              :     /* btcharcmp compares chars as unsigned */
     662            0 :     sksup->low_elem = UInt8GetDatum(0);
     663            0 :     sksup->high_elem = UInt8GetDatum(UCHAR_MAX);
     664              : 
     665            0 :     PG_RETURN_VOID();
     666              : }
        

Generated by: LCOV version 2.0-1