LCOV - code coverage report
Current view: top level - src/backend/utils/adt - pg_lsn.c (source / functions) Hit Total Coverage
Test: PostgreSQL 17devel Lines: 96 105 91.4 %
Date: 2024-04-20 04:11:15 Functions: 17 19 89.5 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * pg_lsn.c
       4             :  *    Operations for the pg_lsn datatype.
       5             :  *
       6             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  * IDENTIFICATION
      10             :  *    src/backend/utils/adt/pg_lsn.c
      11             :  *
      12             :  *-------------------------------------------------------------------------
      13             :  */
      14             : #include "postgres.h"
      15             : 
      16             : #include "libpq/pqformat.h"
      17             : #include "utils/fmgrprotos.h"
      18             : #include "utils/numeric.h"
      19             : #include "utils/pg_lsn.h"
      20             : 
      21             : #define MAXPG_LSNLEN            17
      22             : #define MAXPG_LSNCOMPONENT  8
      23             : 
      24             : /*----------------------------------------------------------
      25             :  * Formatting and conversion routines.
      26             :  *---------------------------------------------------------*/
      27             : 
      28             : XLogRecPtr
      29        7534 : pg_lsn_in_internal(const char *str, bool *have_error)
      30             : {
      31             :     int         len1,
      32             :                 len2;
      33             :     uint32      id,
      34             :                 off;
      35             :     XLogRecPtr  result;
      36             : 
      37             :     Assert(have_error != NULL);
      38        7534 :     *have_error = false;
      39             : 
      40             :     /* Sanity check input format. */
      41        7534 :     len1 = strspn(str, "0123456789abcdefABCDEF");
      42        7534 :     if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/')
      43             :     {
      44          36 :         *have_error = true;
      45          36 :         return InvalidXLogRecPtr;
      46             :     }
      47        7498 :     len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF");
      48        7498 :     if (len2 < 1 || len2 > MAXPG_LSNCOMPONENT || str[len1 + 1 + len2] != '\0')
      49             :     {
      50           6 :         *have_error = true;
      51           6 :         return InvalidXLogRecPtr;
      52             :     }
      53             : 
      54             :     /* Decode result. */
      55        7492 :     id = (uint32) strtoul(str, NULL, 16);
      56        7492 :     off = (uint32) strtoul(str + len1 + 1, NULL, 16);
      57        7492 :     result = ((uint64) id << 32) | off;
      58             : 
      59        7492 :     return result;
      60             : }
      61             : 
      62             : Datum
      63        7522 : pg_lsn_in(PG_FUNCTION_ARGS)
      64             : {
      65        7522 :     char       *str = PG_GETARG_CSTRING(0);
      66             :     XLogRecPtr  result;
      67        7522 :     bool        have_error = false;
      68             : 
      69        7522 :     result = pg_lsn_in_internal(str, &have_error);
      70        7522 :     if (have_error)
      71          42 :         ereturn(fcinfo->context, (Datum) 0,
      72             :                 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
      73             :                  errmsg("invalid input syntax for type %s: \"%s\"",
      74             :                         "pg_lsn", str)));
      75             : 
      76        7480 :     PG_RETURN_LSN(result);
      77             : }
      78             : 
      79             : Datum
      80        5196 : pg_lsn_out(PG_FUNCTION_ARGS)
      81             : {
      82        5196 :     XLogRecPtr  lsn = PG_GETARG_LSN(0);
      83             :     char        buf[MAXPG_LSNLEN + 1];
      84             :     char       *result;
      85             : 
      86        5196 :     snprintf(buf, sizeof buf, "%X/%X", LSN_FORMAT_ARGS(lsn));
      87        5196 :     result = pstrdup(buf);
      88        5196 :     PG_RETURN_CSTRING(result);
      89             : }
      90             : 
      91             : Datum
      92           0 : pg_lsn_recv(PG_FUNCTION_ARGS)
      93             : {
      94           0 :     StringInfo  buf = (StringInfo) PG_GETARG_POINTER(0);
      95             :     XLogRecPtr  result;
      96             : 
      97           0 :     result = pq_getmsgint64(buf);
      98           0 :     PG_RETURN_LSN(result);
      99             : }
     100             : 
     101             : Datum
     102           0 : pg_lsn_send(PG_FUNCTION_ARGS)
     103             : {
     104           0 :     XLogRecPtr  lsn = PG_GETARG_LSN(0);
     105             :     StringInfoData buf;
     106             : 
     107           0 :     pq_begintypsend(&buf);
     108           0 :     pq_sendint64(&buf, lsn);
     109           0 :     PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
     110             : }
     111             : 
     112             : 
     113             : /*----------------------------------------------------------
     114             :  *  Operators for PostgreSQL LSNs
     115             :  *---------------------------------------------------------*/
     116             : 
     117             : Datum
     118       13480 : pg_lsn_eq(PG_FUNCTION_ARGS)
     119             : {
     120       13480 :     XLogRecPtr  lsn1 = PG_GETARG_LSN(0);
     121       13480 :     XLogRecPtr  lsn2 = PG_GETARG_LSN(1);
     122             : 
     123       13480 :     PG_RETURN_BOOL(lsn1 == lsn2);
     124             : }
     125             : 
     126             : Datum
     127          12 : pg_lsn_ne(PG_FUNCTION_ARGS)
     128             : {
     129          12 :     XLogRecPtr  lsn1 = PG_GETARG_LSN(0);
     130          12 :     XLogRecPtr  lsn2 = PG_GETARG_LSN(1);
     131             : 
     132          12 :     PG_RETURN_BOOL(lsn1 != lsn2);
     133             : }
     134             : 
     135             : Datum
     136       13934 : pg_lsn_lt(PG_FUNCTION_ARGS)
     137             : {
     138       13934 :     XLogRecPtr  lsn1 = PG_GETARG_LSN(0);
     139       13934 :     XLogRecPtr  lsn2 = PG_GETARG_LSN(1);
     140             : 
     141       13934 :     PG_RETURN_BOOL(lsn1 < lsn2);
     142             : }
     143             : 
     144             : Datum
     145        4498 : pg_lsn_gt(PG_FUNCTION_ARGS)
     146             : {
     147        4498 :     XLogRecPtr  lsn1 = PG_GETARG_LSN(0);
     148        4498 :     XLogRecPtr  lsn2 = PG_GETARG_LSN(1);
     149             : 
     150        4498 :     PG_RETURN_BOOL(lsn1 > lsn2);
     151             : }
     152             : 
     153             : Datum
     154        4872 : pg_lsn_le(PG_FUNCTION_ARGS)
     155             : {
     156        4872 :     XLogRecPtr  lsn1 = PG_GETARG_LSN(0);
     157        4872 :     XLogRecPtr  lsn2 = PG_GETARG_LSN(1);
     158             : 
     159        4872 :     PG_RETURN_BOOL(lsn1 <= lsn2);
     160             : }
     161             : 
     162             : Datum
     163        3380 : pg_lsn_ge(PG_FUNCTION_ARGS)
     164             : {
     165        3380 :     XLogRecPtr  lsn1 = PG_GETARG_LSN(0);
     166        3380 :     XLogRecPtr  lsn2 = PG_GETARG_LSN(1);
     167             : 
     168        3380 :     PG_RETURN_BOOL(lsn1 >= lsn2);
     169             : }
     170             : 
     171             : Datum
     172          18 : pg_lsn_larger(PG_FUNCTION_ARGS)
     173             : {
     174          18 :     XLogRecPtr  lsn1 = PG_GETARG_LSN(0);
     175          18 :     XLogRecPtr  lsn2 = PG_GETARG_LSN(1);
     176             : 
     177          18 :     PG_RETURN_LSN((lsn1 > lsn2) ? lsn1 : lsn2);
     178             : }
     179             : 
     180             : Datum
     181           6 : pg_lsn_smaller(PG_FUNCTION_ARGS)
     182             : {
     183           6 :     XLogRecPtr  lsn1 = PG_GETARG_LSN(0);
     184           6 :     XLogRecPtr  lsn2 = PG_GETARG_LSN(1);
     185             : 
     186           6 :     PG_RETURN_LSN((lsn1 < lsn2) ? lsn1 : lsn2);
     187             : }
     188             : 
     189             : /* btree index opclass support */
     190             : Datum
     191        3936 : pg_lsn_cmp(PG_FUNCTION_ARGS)
     192             : {
     193        3936 :     XLogRecPtr  a = PG_GETARG_LSN(0);
     194        3936 :     XLogRecPtr  b = PG_GETARG_LSN(1);
     195             : 
     196        3936 :     if (a > b)
     197        2182 :         PG_RETURN_INT32(1);
     198        1754 :     else if (a == b)
     199          14 :         PG_RETURN_INT32(0);
     200             :     else
     201        1740 :         PG_RETURN_INT32(-1);
     202             : }
     203             : 
     204             : /* hash index opclass support */
     205             : Datum
     206        5310 : pg_lsn_hash(PG_FUNCTION_ARGS)
     207             : {
     208             :     /* We can use hashint8 directly */
     209        5310 :     return hashint8(fcinfo);
     210             : }
     211             : 
     212             : Datum
     213          60 : pg_lsn_hash_extended(PG_FUNCTION_ARGS)
     214             : {
     215          60 :     return hashint8extended(fcinfo);
     216             : }
     217             : 
     218             : 
     219             : /*----------------------------------------------------------
     220             :  *  Arithmetic operators on PostgreSQL LSNs.
     221             :  *---------------------------------------------------------*/
     222             : 
     223             : Datum
     224        4022 : pg_lsn_mi(PG_FUNCTION_ARGS)
     225             : {
     226        4022 :     XLogRecPtr  lsn1 = PG_GETARG_LSN(0);
     227        4022 :     XLogRecPtr  lsn2 = PG_GETARG_LSN(1);
     228             :     char        buf[256];
     229             :     Datum       result;
     230             : 
     231             :     /* Output could be as large as plus or minus 2^63 - 1. */
     232        4022 :     if (lsn1 < lsn2)
     233          34 :         snprintf(buf, sizeof buf, "-" UINT64_FORMAT, lsn2 - lsn1);
     234             :     else
     235        3988 :         snprintf(buf, sizeof buf, UINT64_FORMAT, lsn1 - lsn2);
     236             : 
     237             :     /* Convert to numeric. */
     238        4022 :     result = DirectFunctionCall3(numeric_in,
     239             :                                  CStringGetDatum(buf),
     240             :                                  ObjectIdGetDatum(0),
     241             :                                  Int32GetDatum(-1));
     242             : 
     243        4022 :     return result;
     244             : }
     245             : 
     246             : /*
     247             :  * Add the number of bytes to pg_lsn, giving a new pg_lsn.
     248             :  * Must handle both positive and negative numbers of bytes.
     249             :  */
     250             : Datum
     251          60 : pg_lsn_pli(PG_FUNCTION_ARGS)
     252             : {
     253          60 :     XLogRecPtr  lsn = PG_GETARG_LSN(0);
     254          60 :     Numeric     nbytes = PG_GETARG_NUMERIC(1);
     255             :     Datum       num;
     256             :     Datum       res;
     257             :     char        buf[32];
     258             : 
     259          60 :     if (numeric_is_nan(nbytes))
     260           6 :         ereport(ERROR,
     261             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     262             :                  errmsg("cannot add NaN to pg_lsn")));
     263             : 
     264             :     /* Convert to numeric */
     265          54 :     snprintf(buf, sizeof(buf), UINT64_FORMAT, lsn);
     266          54 :     num = DirectFunctionCall3(numeric_in,
     267             :                               CStringGetDatum(buf),
     268             :                               ObjectIdGetDatum(0),
     269             :                               Int32GetDatum(-1));
     270             : 
     271             :     /* Add two numerics */
     272          54 :     res = DirectFunctionCall2(numeric_add,
     273             :                               num,
     274             :                               NumericGetDatum(nbytes));
     275             : 
     276             :     /* Convert to pg_lsn */
     277          54 :     return DirectFunctionCall1(numeric_pg_lsn, res);
     278             : }
     279             : 
     280             : /*
     281             :  * Subtract the number of bytes from pg_lsn, giving a new pg_lsn.
     282             :  * Must handle both positive and negative numbers of bytes.
     283             :  */
     284             : Datum
     285          36 : pg_lsn_mii(PG_FUNCTION_ARGS)
     286             : {
     287          36 :     XLogRecPtr  lsn = PG_GETARG_LSN(0);
     288          36 :     Numeric     nbytes = PG_GETARG_NUMERIC(1);
     289             :     Datum       num;
     290             :     Datum       res;
     291             :     char        buf[32];
     292             : 
     293          36 :     if (numeric_is_nan(nbytes))
     294           6 :         ereport(ERROR,
     295             :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     296             :                  errmsg("cannot subtract NaN from pg_lsn")));
     297             : 
     298             :     /* Convert to numeric */
     299          30 :     snprintf(buf, sizeof(buf), UINT64_FORMAT, lsn);
     300          30 :     num = DirectFunctionCall3(numeric_in,
     301             :                               CStringGetDatum(buf),
     302             :                               ObjectIdGetDatum(0),
     303             :                               Int32GetDatum(-1));
     304             : 
     305             :     /* Subtract two numerics */
     306          30 :     res = DirectFunctionCall2(numeric_sub,
     307             :                               num,
     308             :                               NumericGetDatum(nbytes));
     309             : 
     310             :     /* Convert to pg_lsn */
     311          30 :     return DirectFunctionCall1(numeric_pg_lsn, res);
     312             : }

Generated by: LCOV version 1.14