LCOV - code coverage report
Current view: top level - src/backend/utils/adt - xid.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 98 147 66.7 %
Date: 2024-11-21 08:14:44 Functions: 23 35 65.7 %
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-2024, 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        4880 : xidin(PG_FUNCTION_ARGS)
      34             : {
      35        4880 :     char       *str = PG_GETARG_CSTRING(0);
      36             :     TransactionId result;
      37             : 
      38        4880 :     result = uint32in_subr(str, NULL, "xid", fcinfo->context);
      39        4868 :     PG_RETURN_TRANSACTIONID(result);
      40             : }
      41             : 
      42             : Datum
      43      222606 : xidout(PG_FUNCTION_ARGS)
      44             : {
      45      222606 :     TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
      46      222606 :     char       *result = (char *) palloc(16);
      47             : 
      48      222606 :     snprintf(result, 16, "%lu", (unsigned long) transactionId);
      49      222606 :     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      319870 : xideq(PG_FUNCTION_ARGS)
      82             : {
      83      319870 :     TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
      84      319870 :     TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
      85             : 
      86      319870 :     PG_RETURN_BOOL(TransactionIdEquals(xid1, xid2));
      87             : }
      88             : 
      89             : /*
      90             :  *      xidneq          - are two xids different?
      91             :  */
      92             : Datum
      93         870 : xidneq(PG_FUNCTION_ARGS)
      94             : {
      95         870 :     TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
      96         870 :     TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
      97             : 
      98         870 :     PG_RETURN_BOOL(!TransactionIdEquals(xid1, xid2));
      99             : }
     100             : 
     101             : Datum
     102         192 : hashxid(PG_FUNCTION_ARGS)
     103             : {
     104         192 :     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         332 : xid_age(PG_FUNCTION_ARGS)
     118             : {
     119         332 :     TransactionId xid = PG_GETARG_TRANSACTIONID(0);
     120         332 :     TransactionId now = GetStableLatestTransactionId();
     121             : 
     122             :     /* Permanent XIDs are always infinitely old */
     123         332 :     if (!TransactionIdIsNormal(xid))
     124           0 :         PG_RETURN_INT32(INT_MAX);
     125             : 
     126         332 :     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           2 : mxid_age(PG_FUNCTION_ARGS)
     134             : {
     135           2 :     TransactionId xid = PG_GETARG_TRANSACTIONID(0);
     136           2 :     MultiXactId now = ReadNextMultiXactId();
     137             : 
     138           2 :     if (!MultiXactIdIsValid(xid))
     139           0 :         PG_RETURN_INT32(INT_MAX);
     140             : 
     141           2 :     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       73764 : xidComparator(const void *arg1, const void *arg2)
     153             : {
     154       73764 :     TransactionId xid1 = *(const TransactionId *) arg1;
     155       73764 :     TransactionId xid2 = *(const TransactionId *) arg2;
     156             : 
     157       73764 :     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        1580 : xid8toxid(PG_FUNCTION_ARGS)
     188             : {
     189        1580 :     FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
     190             : 
     191        1580 :     PG_RETURN_TRANSACTIONID(XidFromFullTransactionId(fxid));
     192             : }
     193             : 
     194             : Datum
     195         868 : xid8in(PG_FUNCTION_ARGS)
     196             : {
     197         868 :     char       *str = PG_GETARG_CSTRING(0);
     198             :     uint64      result;
     199             : 
     200         868 :     result = uint64in_subr(str, NULL, "xid8", fcinfo->context);
     201         856 :     PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(result));
     202             : }
     203             : 
     204             : Datum
     205         982 : xid8out(PG_FUNCTION_ARGS)
     206             : {
     207         982 :     FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
     208         982 :     char       *result = (char *) palloc(21);
     209             : 
     210         982 :     snprintf(result, 21, UINT64_FORMAT, U64FromFullTransactionId(fxid));
     211         982 :     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          18 : xid8eq(PG_FUNCTION_ARGS)
     237             : {
     238          18 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     239          18 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     240             : 
     241          18 :     PG_RETURN_BOOL(FullTransactionIdEquals(fxid1, fxid2));
     242             : }
     243             : 
     244             : Datum
     245           8 : xid8ne(PG_FUNCTION_ARGS)
     246             : {
     247           8 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     248           8 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     249             : 
     250           8 :     PG_RETURN_BOOL(!FullTransactionIdEquals(fxid1, fxid2));
     251             : }
     252             : 
     253             : Datum
     254          18 : xid8lt(PG_FUNCTION_ARGS)
     255             : {
     256          18 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     257          18 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     258             : 
     259          18 :     PG_RETURN_BOOL(FullTransactionIdPrecedes(fxid1, fxid2));
     260             : }
     261             : 
     262             : Datum
     263          18 : xid8gt(PG_FUNCTION_ARGS)
     264             : {
     265          18 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     266          18 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     267             : 
     268          18 :     PG_RETURN_BOOL(FullTransactionIdFollows(fxid1, fxid2));
     269             : }
     270             : 
     271             : Datum
     272          18 : xid8le(PG_FUNCTION_ARGS)
     273             : {
     274          18 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     275          18 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     276             : 
     277          18 :     PG_RETURN_BOOL(FullTransactionIdPrecedesOrEquals(fxid1, fxid2));
     278             : }
     279             : 
     280             : Datum
     281          24 : xid8ge(PG_FUNCTION_ARGS)
     282             : {
     283          24 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     284          24 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     285             : 
     286          24 :     PG_RETURN_BOOL(FullTransactionIdFollowsOrEquals(fxid1, fxid2));
     287             : }
     288             : 
     289             : Datum
     290          42 : xid8cmp(PG_FUNCTION_ARGS)
     291             : {
     292          42 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     293          42 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     294             : 
     295          42 :     if (FullTransactionIdFollows(fxid1, fxid2))
     296           6 :         PG_RETURN_INT32(1);
     297          36 :     else if (FullTransactionIdEquals(fxid1, fxid2))
     298          12 :         PG_RETURN_INT32(0);
     299             :     else
     300          24 :         PG_RETURN_INT32(-1);
     301             : }
     302             : 
     303             : Datum
     304          30 : hashxid8(PG_FUNCTION_ARGS)
     305             : {
     306          30 :     return hashint8(fcinfo);
     307             : }
     308             : 
     309             : Datum
     310           0 : hashxid8extended(PG_FUNCTION_ARGS)
     311             : {
     312           0 :     return hashint8extended(fcinfo);
     313             : }
     314             : 
     315             : Datum
     316          24 : xid8_larger(PG_FUNCTION_ARGS)
     317             : {
     318          24 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     319          24 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     320             : 
     321          24 :     if (FullTransactionIdFollows(fxid1, fxid2))
     322           0 :         PG_RETURN_FULLTRANSACTIONID(fxid1);
     323             :     else
     324          24 :         PG_RETURN_FULLTRANSACTIONID(fxid2);
     325             : }
     326             : 
     327             : Datum
     328          24 : xid8_smaller(PG_FUNCTION_ARGS)
     329             : {
     330          24 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     331          24 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     332             : 
     333          24 :     if (FullTransactionIdPrecedes(fxid1, fxid2))
     334          24 :         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           6 : cidin(PG_FUNCTION_ARGS)
     348             : {
     349           6 :     char       *str = PG_GETARG_CSTRING(0);
     350             :     CommandId   result;
     351             : 
     352           6 :     result = uint32in_subr(str, NULL, "cid", fcinfo->context);
     353           6 :     PG_RETURN_COMMANDID(result);
     354             : }
     355             : 
     356             : /*
     357             :  *      cidout  - converts a cid to external representation.
     358             :  */
     359             : Datum
     360         194 : cidout(PG_FUNCTION_ARGS)
     361             : {
     362         194 :     CommandId   c = PG_GETARG_COMMANDID(0);
     363         194 :     char       *result = (char *) palloc(16);
     364             : 
     365         194 :     snprintf(result, 16, "%lu", (unsigned long) c);
     366         194 :     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 1.14