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

Generated by: LCOV version 1.14