LCOV - differential code coverage report
Current view: top level - src/backend/utils/adt - xid.c (source / functions) Coverage Total Hit LBC UIC UBC GBC GIC GNC CBC EUB ECB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 69.5 % 141 98 2 26 15 3 55 6 34 25 60 2
Current Date: 2023-04-08 15:15:32 Functions: 72.4 % 29 21 8 20 1 8 19 1
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

           TLA  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 CBC        4844 : xidin(PG_FUNCTION_ARGS)
      32                 : {
      33            4844 :     char       *str = PG_GETARG_CSTRING(0);
      34                 :     TransactionId result;
      35                 : 
      36 GNC        4844 :     result = uint32in_subr(str, NULL, "xid", fcinfo->context);
      37            4838 :     PG_RETURN_TRANSACTIONID(result);
      38 ECB             : }
      39                 : 
      40                 : Datum
      41 GIC       77402 : xidout(PG_FUNCTION_ARGS)
      42                 : {
      43 CBC       77402 :     TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
      44 GIC       77402 :     char       *result = (char *) palloc(16);
      45 ECB             : 
      46 CBC       77402 :     snprintf(result, 16, "%lu", (unsigned long) transactionId);
      47 GIC       77402 :     PG_RETURN_CSTRING(result);
      48 ECB             : }
      49                 : 
      50                 : /*
      51                 :  *      xidrecv         - converts external binary format to xid
      52                 :  */
      53                 : Datum
      54 UIC           0 : xidrecv(PG_FUNCTION_ARGS)
      55                 : {
      56 UBC           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      57                 : 
      58               0 :     PG_RETURN_TRANSACTIONID((TransactionId) pq_getmsgint(buf, sizeof(TransactionId)));
      59                 : }
      60 EUB             : 
      61                 : /*
      62                 :  *      xidsend         - converts xid to binary format
      63                 :  */
      64                 : Datum
      65 UIC           0 : xidsend(PG_FUNCTION_ARGS)
      66                 : {
      67 UBC           0 :     TransactionId arg1 = PG_GETARG_TRANSACTIONID(0);
      68                 :     StringInfoData buf;
      69 EUB             : 
      70 UIC           0 :     pq_begintypsend(&buf);
      71               0 :     pq_sendint32(&buf, arg1);
      72 UBC           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
      73 EUB             : }
      74                 : 
      75                 : /*
      76                 :  *      xideq           - are two xids equal?
      77                 :  */
      78                 : Datum
      79 GIC      371283 : xideq(PG_FUNCTION_ARGS)
      80                 : {
      81 CBC      371283 :     TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
      82 GIC      371283 :     TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
      83 ECB             : 
      84 CBC      371283 :     PG_RETURN_BOOL(TransactionIdEquals(xid1, xid2));
      85                 : }
      86 ECB             : 
      87                 : /*
      88                 :  *      xidneq          - are two xids different?
      89                 :  */
      90                 : Datum
      91 GIC         432 : xidneq(PG_FUNCTION_ARGS)
      92                 : {
      93 CBC         432 :     TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
      94 GIC         432 :     TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
      95 ECB             : 
      96 CBC         432 :     PG_RETURN_BOOL(!TransactionIdEquals(xid1, xid2));
      97                 : }
      98 ECB             : 
      99                 : /*
     100                 :  *      xid_age         - compute age of an XID (relative to latest stable xid)
     101                 :  */
     102                 : Datum
     103 GIC         113 : xid_age(PG_FUNCTION_ARGS)
     104                 : {
     105 CBC         113 :     TransactionId xid = PG_GETARG_TRANSACTIONID(0);
     106 GIC         113 :     TransactionId now = GetStableLatestTransactionId();
     107 ECB             : 
     108                 :     /* Permanent XIDs are always infinitely old */
     109 GIC         113 :     if (!TransactionIdIsNormal(xid))
     110 UIC           0 :         PG_RETURN_INT32(INT_MAX);
     111 ECB             : 
     112 GBC         113 :     PG_RETURN_INT32((int32) (now - xid));
     113                 : }
     114 ECB             : 
     115                 : /*
     116                 :  *      mxid_age            - compute age of a multi XID (relative to latest stable mxid)
     117                 :  */
     118                 : Datum
     119 GIC           1 : mxid_age(PG_FUNCTION_ARGS)
     120                 : {
     121 CBC           1 :     TransactionId xid = PG_GETARG_TRANSACTIONID(0);
     122 GIC           1 :     MultiXactId now = ReadNextMultiXactId();
     123 ECB             : 
     124 CBC           1 :     if (!MultiXactIdIsValid(xid))
     125 UIC           0 :         PG_RETURN_INT32(INT_MAX);
     126 ECB             : 
     127 GBC           1 :     PG_RETURN_INT32((int32) (now - xid));
     128                 : }
     129 ECB             : 
     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 GIC       36048 : xidComparator(const void *arg1, const void *arg2)
     139                 : {
     140 CBC       36048 :     TransactionId xid1 = *(const TransactionId *) arg1;
     141 GIC       36048 :     TransactionId xid2 = *(const TransactionId *) arg2;
     142 ECB             : 
     143 CBC       36048 :     if (xid1 > xid2)
     144 GIC        6439 :         return 1;
     145 CBC       29609 :     if (xid1 < xid2)
     146           24910 :         return -1;
     147            4699 :     return 0;
     148 ECB             : }
     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 UIC           0 : xidLogicalComparator(const void *arg1, const void *arg2)
     160                 : {
     161 UBC           0 :     TransactionId xid1 = *(const TransactionId *) arg1;
     162 UIC           0 :     TransactionId xid2 = *(const TransactionId *) arg2;
     163 EUB             : 
     164 UBC           0 :     Assert(TransactionIdIsNormal(xid1));
     165 UIC           0 :     Assert(TransactionIdIsNormal(xid2));
     166 EUB             : 
     167 UBC           0 :     if (TransactionIdPrecedes(xid1, xid2))
     168 UIC           0 :         return -1;
     169 EUB             : 
     170 UBC           0 :     if (TransactionIdPrecedes(xid2, xid1))
     171 UIC           0 :         return 1;
     172 EUB             : 
     173 UBC           0 :     return 0;
     174                 : }
     175 EUB             : 
     176                 : Datum
     177 GIC         802 : xid8toxid(PG_FUNCTION_ARGS)
     178                 : {
     179 CBC         802 :     FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
     180                 : 
     181             802 :     PG_RETURN_TRANSACTIONID(XidFromFullTransactionId(fxid));
     182                 : }
     183 ECB             : 
     184                 : Datum
     185 GIC         433 : xid8in(PG_FUNCTION_ARGS)
     186                 : {
     187 CBC         433 :     char       *str = PG_GETARG_CSTRING(0);
     188                 :     uint64      result;
     189                 : 
     190 GNC         433 :     result = uint64in_subr(str, NULL, "xid8", fcinfo->context);
     191             427 :     PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(result));
     192                 : }
     193                 : 
     194 ECB             : Datum
     195 CBC         369 : xid8out(PG_FUNCTION_ARGS)
     196                 : {
     197 GIC         369 :     FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
     198             369 :     char       *result = (char *) palloc(21);
     199 ECB             : 
     200 GIC         369 :     snprintf(result, 21, UINT64_FORMAT, U64FromFullTransactionId(fxid));
     201 CBC         369 :     PG_RETURN_CSTRING(result);
     202 ECB             : }
     203                 : 
     204                 : Datum
     205 LBC           0 : xid8recv(PG_FUNCTION_ARGS)
     206                 : {
     207 UIC           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
     208                 :     uint64      value;
     209 EUB             : 
     210 UIC           0 :     value = (uint64) pq_getmsgint64(buf);
     211 UBC           0 :     PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(value));
     212                 : }
     213                 : 
     214 EUB             : Datum
     215 UBC           0 : xid8send(PG_FUNCTION_ARGS)
     216                 : {
     217 UIC           0 :     FullTransactionId arg1 = PG_GETARG_FULLTRANSACTIONID(0);
     218                 :     StringInfoData buf;
     219 EUB             : 
     220 UIC           0 :     pq_begintypsend(&buf);
     221 UBC           0 :     pq_sendint64(&buf, (uint64) U64FromFullTransactionId(arg1));
     222 UIC           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     223                 : }
     224 EUB             : 
     225                 : Datum
     226 GBC           9 : xid8eq(PG_FUNCTION_ARGS)
     227                 : {
     228 GIC           9 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     229               9 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     230 ECB             : 
     231 GIC           9 :     PG_RETURN_BOOL(FullTransactionIdEquals(fxid1, fxid2));
     232 ECB             : }
     233                 : 
     234                 : Datum
     235 CBC           4 : xid8ne(PG_FUNCTION_ARGS)
     236                 : {
     237 GIC           4 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     238               4 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     239 ECB             : 
     240 GIC           4 :     PG_RETURN_BOOL(!FullTransactionIdEquals(fxid1, fxid2));
     241 ECB             : }
     242                 : 
     243                 : Datum
     244 CBC           9 : xid8lt(PG_FUNCTION_ARGS)
     245                 : {
     246 GIC           9 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     247               9 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     248 ECB             : 
     249 GIC           9 :     PG_RETURN_BOOL(FullTransactionIdPrecedes(fxid1, fxid2));
     250 ECB             : }
     251                 : 
     252                 : Datum
     253 CBC           9 : xid8gt(PG_FUNCTION_ARGS)
     254                 : {
     255 GIC           9 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     256               9 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     257 ECB             : 
     258 GIC           9 :     PG_RETURN_BOOL(FullTransactionIdFollows(fxid1, fxid2));
     259 ECB             : }
     260                 : 
     261                 : Datum
     262 CBC           9 : xid8le(PG_FUNCTION_ARGS)
     263                 : {
     264 GIC           9 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     265               9 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     266 ECB             : 
     267 GIC           9 :     PG_RETURN_BOOL(FullTransactionIdPrecedesOrEquals(fxid1, fxid2));
     268 ECB             : }
     269                 : 
     270                 : Datum
     271 CBC          12 : xid8ge(PG_FUNCTION_ARGS)
     272                 : {
     273 GIC          12 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     274              12 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     275 ECB             : 
     276 GIC          12 :     PG_RETURN_BOOL(FullTransactionIdFollowsOrEquals(fxid1, fxid2));
     277 ECB             : }
     278                 : 
     279                 : Datum
     280 CBC          21 : xid8cmp(PG_FUNCTION_ARGS)
     281                 : {
     282 GIC          21 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     283              21 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     284 ECB             : 
     285 GIC          21 :     if (FullTransactionIdFollows(fxid1, fxid2))
     286 CBC           3 :         PG_RETURN_INT32(1);
     287              18 :     else if (FullTransactionIdEquals(fxid1, fxid2))
     288 GIC           6 :         PG_RETURN_INT32(0);
     289 ECB             :     else
     290 CBC          12 :         PG_RETURN_INT32(-1);
     291 ECB             : }
     292                 : 
     293                 : Datum
     294 CBC          12 : xid8_larger(PG_FUNCTION_ARGS)
     295                 : {
     296 GIC          12 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     297              12 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     298 ECB             : 
     299 GIC          12 :     if (FullTransactionIdFollows(fxid1, fxid2))
     300 LBC           0 :         PG_RETURN_FULLTRANSACTIONID(fxid1);
     301 ECB             :     else
     302 GIC          12 :         PG_RETURN_FULLTRANSACTIONID(fxid2);
     303 ECB             : }
     304 EUB             : 
     305                 : Datum
     306 CBC          12 : xid8_smaller(PG_FUNCTION_ARGS)
     307                 : {
     308 GIC          12 :     FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
     309              12 :     FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
     310 ECB             : 
     311 GIC          12 :     if (FullTransactionIdPrecedes(fxid1, fxid2))
     312 CBC          12 :         PG_RETURN_FULLTRANSACTIONID(fxid1);
     313 ECB             :     else
     314 UIC           0 :         PG_RETURN_FULLTRANSACTIONID(fxid2);
     315 ECB             : }
     316                 : 
     317                 : /*****************************************************************************
     318 EUB             :  *   COMMAND IDENTIFIER ROUTINES                                             *
     319                 :  *****************************************************************************/
     320                 : 
     321                 : /*
     322                 :  *      cidin   - converts CommandId to internal representation.
     323                 :  */
     324                 : Datum
     325 GIC           3 : cidin(PG_FUNCTION_ARGS)
     326                 : {
     327               3 :     char       *str = PG_GETARG_CSTRING(0);
     328                 :     CommandId   result;
     329                 : 
     330 GNC           3 :     result = uint32in_subr(str, NULL, "cid", fcinfo->context);
     331               3 :     PG_RETURN_COMMANDID(result);
     332                 : }
     333 ECB             : 
     334                 : /*
     335                 :  *      cidout  - converts a cid to external representation.
     336                 :  */
     337                 : Datum
     338 GIC          97 : cidout(PG_FUNCTION_ARGS)
     339                 : {
     340              97 :     CommandId   c = PG_GETARG_COMMANDID(0);
     341              97 :     char       *result = (char *) palloc(16);
     342                 : 
     343              97 :     snprintf(result, 16, "%lu", (unsigned long) c);
     344 CBC          97 :     PG_RETURN_CSTRING(result);
     345                 : }
     346 ECB             : 
     347                 : /*
     348                 :  *      cidrecv         - converts external binary format to cid
     349                 :  */
     350                 : Datum
     351 UIC           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 EUB             : 
     358                 : /*
     359                 :  *      cidsend         - converts cid to binary format
     360                 :  */
     361                 : Datum
     362 UIC           0 : cidsend(PG_FUNCTION_ARGS)
     363                 : {
     364               0 :     CommandId   arg1 = PG_GETARG_COMMANDID(0);
     365                 :     StringInfoData buf;
     366                 : 
     367               0 :     pq_begintypsend(&buf);
     368 UBC           0 :     pq_sendint32(&buf, arg1);
     369 UIC           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     370 EUB             : }
     371                 : 
     372                 : Datum
     373 UBC           0 : cideq(PG_FUNCTION_ARGS)
     374 EUB             : {
     375 UBC           0 :     CommandId   arg1 = PG_GETARG_COMMANDID(0);
     376 UIC           0 :     CommandId   arg2 = PG_GETARG_COMMANDID(1);
     377                 : 
     378               0 :     PG_RETURN_BOOL(arg1 == arg2);
     379 EUB             : }
        

Generated by: LCOV version v1.16-55-g56c0a2a