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

Generated by: LCOV version 1.14