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

Generated by: LCOV version 1.14