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

Generated by: LCOV version 1.14