LCOV - code coverage report
Current view: top level - src/backend/utils/adt - xid.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 66.7 % 147 98
Test Date: 2026-03-21 21:15:49 Functions: 65.7 % 35 23
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * xid.c
       4              :  *    POSTGRES transaction identifier and command identifier datatypes.
       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/utils/adt/xid.c
      12              :  *
      13              :  *-------------------------------------------------------------------------
      14              :  */
      15              : #include "postgres.h"
      16              : 
      17              : #include <limits.h>
      18              : 
      19              : #include "access/multixact.h"
      20              : #include "access/transam.h"
      21              : #include "access/xact.h"
      22              : #include "common/hashfn.h"
      23              : #include "common/int.h"
      24              : #include "libpq/pqformat.h"
      25              : #include "utils/builtins.h"
      26              : #include "utils/xid8.h"
      27              : 
      28              : #define PG_GETARG_COMMANDID(n)      DatumGetCommandId(PG_GETARG_DATUM(n))
      29              : #define PG_RETURN_COMMANDID(x)      return CommandIdGetDatum(x)
      30              : 
      31              : 
      32              : Datum
      33       201342 : xidin(PG_FUNCTION_ARGS)
      34              : {
      35       201342 :     char       *str = PG_GETARG_CSTRING(0);
      36              :     TransactionId result;
      37              : 
      38       201342 :     result = uint32in_subr(str, NULL, "xid", fcinfo->context);
      39       201334 :     PG_RETURN_TRANSACTIONID(result);
      40              : }
      41              : 
      42              : Datum
      43       186289 : xidout(PG_FUNCTION_ARGS)
      44              : {
      45       186289 :     TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
      46       186289 :     char       *result = (char *) palloc(16);
      47              : 
      48       186289 :     snprintf(result, 16, "%u", transactionId);
      49       186289 :     PG_RETURN_CSTRING(result);
      50              : }
      51              : 
      52              : /*
      53              :  *      xidrecv         - converts external binary format to xid
      54              :  */
      55              : Datum
      56            0 : xidrecv(PG_FUNCTION_ARGS)
      57              : {
      58            0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      59              : 
      60            0 :     PG_RETURN_TRANSACTIONID((TransactionId) pq_getmsgint(buf, sizeof(TransactionId)));
      61              : }
      62              : 
      63              : /*
      64              :  *      xidsend         - converts xid to binary format
      65              :  */
      66              : Datum
      67            0 : xidsend(PG_FUNCTION_ARGS)
      68              : {
      69            0 :     TransactionId arg1 = PG_GETARG_TRANSACTIONID(0);
      70              :     StringInfoData buf;
      71              : 
      72            0 :     pq_begintypsend(&buf);
      73            0 :     pq_sendint32(&buf, arg1);
      74            0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
      75              : }
      76              : 
      77              : /*
      78              :  *      xideq           - are two xids equal?
      79              :  */
      80              : Datum
      81       234164 : xideq(PG_FUNCTION_ARGS)
      82              : {
      83       234164 :     TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
      84       234164 :     TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
      85              : 
      86       234164 :     PG_RETURN_BOOL(TransactionIdEquals(xid1, xid2));
      87              : }
      88              : 
      89              : /*
      90              :  *      xidneq          - are two xids different?
      91              :  */
      92              : Datum
      93          476 : xidneq(PG_FUNCTION_ARGS)
      94              : {
      95          476 :     TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
      96          476 :     TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
      97              : 
      98          476 :     PG_RETURN_BOOL(!TransactionIdEquals(xid1, xid2));
      99              : }
     100              : 
     101              : Datum
     102          128 : hashxid(PG_FUNCTION_ARGS)
     103              : {
     104          128 :     return hash_uint32(PG_GETARG_TRANSACTIONID(0));
     105              : }
     106              : 
     107              : Datum
     108            0 : hashxidextended(PG_FUNCTION_ARGS)
     109              : {
     110            0 :     return hash_uint32_extended(PG_GETARG_TRANSACTIONID(0), PG_GETARG_INT64(1));
     111              : }
     112              : 
     113              : /*
     114              :  *      xid_age         - compute age of an XID (relative to latest stable xid)
     115              :  */
     116              : Datum
     117          159 : xid_age(PG_FUNCTION_ARGS)
     118              : {
     119          159 :     TransactionId xid = PG_GETARG_TRANSACTIONID(0);
     120          159 :     TransactionId now = GetStableLatestTransactionId();
     121              : 
     122              :     /* Permanent XIDs are always infinitely old */
     123          159 :     if (!TransactionIdIsNormal(xid))
     124            0 :         PG_RETURN_INT32(INT_MAX);
     125              : 
     126          159 :     PG_RETURN_INT32((int32) (now - xid));
     127              : }
     128              : 
     129              : /*
     130              :  *      mxid_age            - compute age of a multi XID (relative to latest stable mxid)
     131              :  */
     132              : Datum
     133            1 : mxid_age(PG_FUNCTION_ARGS)
     134              : {
     135            1 :     TransactionId xid = PG_GETARG_TRANSACTIONID(0);
     136            1 :     MultiXactId now = ReadNextMultiXactId();
     137              : 
     138            1 :     if (!MultiXactIdIsValid(xid))
     139            0 :         PG_RETURN_INT32(INT_MAX);
     140              : 
     141            1 :     PG_RETURN_INT32((int32) (now - xid));
     142              : }
     143              : 
     144              : /*
     145              :  * xidComparator
     146              :  *      qsort comparison function for XIDs
     147              :  *
     148              :  * We can't use wraparound comparison for XIDs because that does not respect
     149              :  * the triangle inequality!  Any old sort order will do.
     150              :  */
     151              : int
     152        46494 : xidComparator(const void *arg1, const void *arg2)
     153              : {
     154        46494 :     TransactionId xid1 = *(const TransactionId *) arg1;
     155        46494 :     TransactionId xid2 = *(const TransactionId *) arg2;
     156              : 
     157        46494 :     return pg_cmp_u32(xid1, xid2);
     158              : }
     159              : 
     160              : /*
     161              :  * xidLogicalComparator
     162              :  *      qsort comparison function for XIDs
     163              :  *
     164              :  * This is used to compare only XIDs from the same epoch (e.g. for backends
     165              :  * running at the same time). So there must be only normal XIDs, so there's
     166              :  * no issue with triangle inequality.
     167              :  */
     168              : int
     169            0 : xidLogicalComparator(const void *arg1, const void *arg2)
     170              : {
     171            0 :     TransactionId xid1 = *(const TransactionId *) arg1;
     172            0 :     TransactionId xid2 = *(const TransactionId *) arg2;
     173              : 
     174              :     Assert(TransactionIdIsNormal(xid1));
     175              :     Assert(TransactionIdIsNormal(xid2));
     176              : 
     177            0 :     if (TransactionIdPrecedes(xid1, xid2))
     178            0 :         return -1;
     179              : 
     180            0 :     if (TransactionIdPrecedes(xid2, xid1))
     181            0 :         return 1;
     182              : 
     183            0 :     return 0;
     184              : }
     185              : 
     186              : Datum
     187         1073 : xid8toxid(PG_FUNCTION_ARGS)
     188              : {
     189         1073 :     FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
     190              : 
     191         1073 :     PG_RETURN_TRANSACTIONID(XidFromFullTransactionId(fxid));
     192              : }
     193              : 
     194              : Datum
     195          581 : xid8in(PG_FUNCTION_ARGS)
     196              : {
     197          581 :     char       *str = PG_GETARG_CSTRING(0);
     198              :     uint64      result;
     199              : 
     200          581 :     result = uint64in_subr(str, NULL, "xid8", fcinfo->context);
     201          573 :     PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(result));
     202              : }
     203              : 
     204              : Datum
     205          608 : xid8out(PG_FUNCTION_ARGS)
     206              : {
     207          608 :     FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
     208          608 :     char       *result = (char *) palloc(21);
     209              : 
     210          608 :     snprintf(result, 21, UINT64_FORMAT, U64FromFullTransactionId(fxid));
     211          608 :     PG_RETURN_CSTRING(result);
     212              : }
     213              : 
     214              : Datum
     215            0 : xid8recv(PG_FUNCTION_ARGS)
     216              : {
     217            0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     218              :     uint64      value;
     219              : 
     220            0 :     value = (uint64) pq_getmsgint64(buf);
     221            0 :     PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(value));
     222              : }
     223              : 
     224              : Datum
     225            0 : xid8send(PG_FUNCTION_ARGS)
     226              : {
     227            0 :     FullTransactionId arg1 = PG_GETARG_FULLTRANSACTIONID(0);
     228              :     StringInfoData buf;
     229              : 
     230            0 :     pq_begintypsend(&buf);
     231            0 :     pq_sendint64(&buf, (uint64) U64FromFullTransactionId(arg1));
     232            0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     233              : }
     234              : 
     235              : Datum
     236           12 : xid8eq(PG_FUNCTION_ARGS)
     237              : {
     238           12 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     239           12 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     240              : 
     241           12 :     PG_RETURN_BOOL(FullTransactionIdEquals(fxid1, fxid2));
     242              : }
     243              : 
     244              : Datum
     245            6 : xid8ne(PG_FUNCTION_ARGS)
     246              : {
     247            6 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     248            6 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     249              : 
     250            6 :     PG_RETURN_BOOL(!FullTransactionIdEquals(fxid1, fxid2));
     251              : }
     252              : 
     253              : Datum
     254           15 : xid8lt(PG_FUNCTION_ARGS)
     255              : {
     256           15 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     257           15 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     258              : 
     259           15 :     PG_RETURN_BOOL(FullTransactionIdPrecedes(fxid1, fxid2));
     260              : }
     261              : 
     262              : Datum
     263           15 : xid8gt(PG_FUNCTION_ARGS)
     264              : {
     265           15 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     266           15 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     267              : 
     268           15 :     PG_RETURN_BOOL(FullTransactionIdFollows(fxid1, fxid2));
     269              : }
     270              : 
     271              : Datum
     272           15 : xid8le(PG_FUNCTION_ARGS)
     273              : {
     274           15 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     275           15 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     276              : 
     277           15 :     PG_RETURN_BOOL(FullTransactionIdPrecedesOrEquals(fxid1, fxid2));
     278              : }
     279              : 
     280              : Datum
     281           28 : xid8ge(PG_FUNCTION_ARGS)
     282              : {
     283           28 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     284           28 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     285              : 
     286           28 :     PG_RETURN_BOOL(FullTransactionIdFollowsOrEquals(fxid1, fxid2));
     287              : }
     288              : 
     289              : Datum
     290           31 : xid8cmp(PG_FUNCTION_ARGS)
     291              : {
     292           31 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     293           31 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     294              : 
     295           31 :     if (FullTransactionIdFollows(fxid1, fxid2))
     296            5 :         PG_RETURN_INT32(1);
     297           26 :     else if (FullTransactionIdEquals(fxid1, fxid2))
     298            9 :         PG_RETURN_INT32(0);
     299              :     else
     300           17 :         PG_RETURN_INT32(-1);
     301              : }
     302              : 
     303              : Datum
     304           20 : hashxid8(PG_FUNCTION_ARGS)
     305              : {
     306           20 :     return hashint8(fcinfo);
     307              : }
     308              : 
     309              : Datum
     310            0 : hashxid8extended(PG_FUNCTION_ARGS)
     311              : {
     312            0 :     return hashint8extended(fcinfo);
     313              : }
     314              : 
     315              : Datum
     316           16 : xid8_larger(PG_FUNCTION_ARGS)
     317              : {
     318           16 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     319           16 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     320              : 
     321           16 :     if (FullTransactionIdFollows(fxid1, fxid2))
     322            0 :         PG_RETURN_FULLTRANSACTIONID(fxid1);
     323              :     else
     324           16 :         PG_RETURN_FULLTRANSACTIONID(fxid2);
     325              : }
     326              : 
     327              : Datum
     328           16 : xid8_smaller(PG_FUNCTION_ARGS)
     329              : {
     330           16 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     331           16 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     332              : 
     333           16 :     if (FullTransactionIdPrecedes(fxid1, fxid2))
     334           16 :         PG_RETURN_FULLTRANSACTIONID(fxid1);
     335              :     else
     336            0 :         PG_RETURN_FULLTRANSACTIONID(fxid2);
     337              : }
     338              : 
     339              : /*****************************************************************************
     340              :  *   COMMAND IDENTIFIER ROUTINES                                             *
     341              :  *****************************************************************************/
     342              : 
     343              : /*
     344              :  *      cidin   - converts CommandId to internal representation.
     345              :  */
     346              : Datum
     347            4 : cidin(PG_FUNCTION_ARGS)
     348              : {
     349            4 :     char       *str = PG_GETARG_CSTRING(0);
     350              :     CommandId   result;
     351              : 
     352            4 :     result = uint32in_subr(str, NULL, "cid", fcinfo->context);
     353            4 :     PG_RETURN_COMMANDID(result);
     354              : }
     355              : 
     356              : /*
     357              :  *      cidout  - converts a cid to external representation.
     358              :  */
     359              : Datum
     360          128 : cidout(PG_FUNCTION_ARGS)
     361              : {
     362          128 :     CommandId   c = PG_GETARG_COMMANDID(0);
     363          128 :     char       *result = (char *) palloc(16);
     364              : 
     365          128 :     snprintf(result, 16, "%u", c);
     366          128 :     PG_RETURN_CSTRING(result);
     367              : }
     368              : 
     369              : /*
     370              :  *      cidrecv         - converts external binary format to cid
     371              :  */
     372              : Datum
     373            0 : cidrecv(PG_FUNCTION_ARGS)
     374              : {
     375            0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     376              : 
     377            0 :     PG_RETURN_COMMANDID((CommandId) pq_getmsgint(buf, sizeof(CommandId)));
     378              : }
     379              : 
     380              : /*
     381              :  *      cidsend         - converts cid to binary format
     382              :  */
     383              : Datum
     384            0 : cidsend(PG_FUNCTION_ARGS)
     385              : {
     386            0 :     CommandId   arg1 = PG_GETARG_COMMANDID(0);
     387              :     StringInfoData buf;
     388              : 
     389            0 :     pq_begintypsend(&buf);
     390            0 :     pq_sendint32(&buf, arg1);
     391            0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     392              : }
     393              : 
     394              : Datum
     395            0 : cideq(PG_FUNCTION_ARGS)
     396              : {
     397            0 :     CommandId   arg1 = PG_GETARG_COMMANDID(0);
     398            0 :     CommandId   arg2 = PG_GETARG_COMMANDID(1);
     399              : 
     400            0 :     PG_RETURN_BOOL(arg1 == arg2);
     401              : }
     402              : 
     403              : Datum
     404            0 : hashcid(PG_FUNCTION_ARGS)
     405              : {
     406            0 :     return hash_uint32(PG_GETARG_COMMANDID(0));
     407              : }
     408              : 
     409              : Datum
     410            0 : hashcidextended(PG_FUNCTION_ARGS)
     411              : {
     412            0 :     return hash_uint32_extended(PG_GETARG_COMMANDID(0), PG_GETARG_INT64(1));
     413              : }
        

Generated by: LCOV version 2.0-1