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

Generated by: LCOV version 1.13