PostgreSQL Source Code git master
pg_lsn.c
Go to the documentation of this file.
1/*-------------------------------------------------------------------------
2 *
3 * pg_lsn.c
4 * Operations for the pg_lsn datatype.
5 *
6 * Portions Copyright (c) 1996-2025, 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/*
29 * Internal version of pg_lsn_in() with support for soft error reporting.
30 */
32pg_lsn_in_safe(const char *str, Node *escontext)
33{
34 int len1,
35 len2;
36 uint32 id,
37 off;
38 XLogRecPtr result;
39
40 /* Sanity check input format. */
41 len1 = strspn(str, "0123456789abcdefABCDEF");
42 if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/')
43 goto syntax_error;
44
45 len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF");
46 if (len2 < 1 || len2 > MAXPG_LSNCOMPONENT || str[len1 + 1 + len2] != '\0')
47 goto syntax_error;
48
49 /* Decode result. */
50 id = (uint32) strtoul(str, NULL, 16);
51 off = (uint32) strtoul(str + len1 + 1, NULL, 16);
52 result = ((uint64) id << 32) | off;
53
54 return result;
55
57 ereturn(escontext, InvalidXLogRecPtr,
58 (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
59 errmsg("invalid input syntax for type %s: \"%s\"",
60 "pg_lsn", str)));
61}
62
65{
66 char *str = PG_GETARG_CSTRING(0);
67 XLogRecPtr result;
68
69 result = pg_lsn_in_safe(str, fcinfo->context);
70
71 PG_RETURN_LSN(result);
72}
73
76{
78 char buf[MAXPG_LSNLEN + 1];
79 char *result;
80
81 snprintf(buf, sizeof buf, "%X/%08X", LSN_FORMAT_ARGS(lsn));
82 result = pstrdup(buf);
83 PG_RETURN_CSTRING(result);
84}
85
88{
90 XLogRecPtr result;
91
92 result = pq_getmsgint64(buf);
93 PG_RETURN_LSN(result);
94}
95
98{
101
103 pq_sendint64(&buf, lsn);
105}
106
107
108/*----------------------------------------------------------
109 * Operators for PostgreSQL LSNs
110 *---------------------------------------------------------*/
111
112Datum
114{
115 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
116 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
117
118 PG_RETURN_BOOL(lsn1 == lsn2);
119}
120
121Datum
123{
124 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
125 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
126
127 PG_RETURN_BOOL(lsn1 != lsn2);
128}
129
130Datum
132{
133 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
134 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
135
136 PG_RETURN_BOOL(lsn1 < lsn2);
137}
138
139Datum
141{
142 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
143 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
144
145 PG_RETURN_BOOL(lsn1 > lsn2);
146}
147
148Datum
150{
151 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
152 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
153
154 PG_RETURN_BOOL(lsn1 <= lsn2);
155}
156
157Datum
159{
160 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
161 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
162
163 PG_RETURN_BOOL(lsn1 >= lsn2);
164}
165
166Datum
168{
169 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
170 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
171
172 PG_RETURN_LSN((lsn1 > lsn2) ? lsn1 : lsn2);
173}
174
175Datum
177{
178 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
179 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
180
181 PG_RETURN_LSN((lsn1 < lsn2) ? lsn1 : lsn2);
182}
183
184/* btree index opclass support */
185Datum
187{
190
191 if (a > b)
193 else if (a == b)
195 else
196 PG_RETURN_INT32(-1);
197}
198
199/* hash index opclass support */
200Datum
202{
203 /* We can use hashint8 directly */
204 return hashint8(fcinfo);
205}
206
207Datum
209{
210 return hashint8extended(fcinfo);
211}
212
213
214/*----------------------------------------------------------
215 * Arithmetic operators on PostgreSQL LSNs.
216 *---------------------------------------------------------*/
217
218Datum
220{
221 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
222 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
223 char buf[256];
224 Datum result;
225
226 /* Output could be as large as plus or minus 2^63 - 1. */
227 if (lsn1 < lsn2)
228 snprintf(buf, sizeof buf, "-" UINT64_FORMAT, lsn2 - lsn1);
229 else
230 snprintf(buf, sizeof buf, UINT64_FORMAT, lsn1 - lsn2);
231
232 /* Convert to numeric. */
236 Int32GetDatum(-1));
237
238 return result;
239}
240
241/*
242 * Add the number of bytes to pg_lsn, giving a new pg_lsn.
243 * Must handle both positive and negative numbers of bytes.
244 */
245Datum
247{
248 XLogRecPtr lsn = PG_GETARG_LSN(0);
249 Numeric nbytes = PG_GETARG_NUMERIC(1);
250 Datum num;
251 Datum res;
252 char buf[32];
253
254 if (numeric_is_nan(nbytes))
256 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
257 errmsg("cannot add NaN to pg_lsn")));
258
259 /* Convert to numeric */
260 snprintf(buf, sizeof(buf), UINT64_FORMAT, lsn);
264 Int32GetDatum(-1));
265
266 /* Add two numerics */
268 num,
269 NumericGetDatum(nbytes));
270
271 /* Convert to pg_lsn */
273}
274
275/*
276 * Subtract the number of bytes from pg_lsn, giving a new pg_lsn.
277 * Must handle both positive and negative numbers of bytes.
278 */
279Datum
281{
282 XLogRecPtr lsn = PG_GETARG_LSN(0);
283 Numeric nbytes = PG_GETARG_NUMERIC(1);
284 Datum num;
285 Datum res;
286 char buf[32];
287
288 if (numeric_is_nan(nbytes))
290 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
291 errmsg("cannot subtract NaN from pg_lsn")));
292
293 /* Convert to numeric */
294 snprintf(buf, sizeof(buf), UINT64_FORMAT, lsn);
298 Int32GetDatum(-1));
299
300 /* Subtract two numerics */
302 num,
303 NumericGetDatum(nbytes));
304
305 /* Convert to pg_lsn */
307}
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition: numeric.c:2940
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:626
bool numeric_is_nan(Numeric num)
Definition: numeric.c:834
Datum numeric_add(PG_FUNCTION_ARGS)
Definition: numeric.c:2865
Datum numeric_pg_lsn(PG_FUNCTION_ARGS)
Definition: numeric.c:4679
#define UINT64_FORMAT
Definition: c.h:562
uint64_t uint64
Definition: c.h:544
uint32_t uint32
Definition: c.h:543
int errcode(int sqlerrcode)
Definition: elog.c:863
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ereturn(context, dummy_value,...)
Definition: elog.h:278
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:150
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:684
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:682
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:686
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
const char * str
Datum hashint8extended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:103
Datum hashint8(PG_FUNCTION_ARGS)
Definition: hashfunc.c:83
int b
Definition: isn.c:74
int a
Definition: isn.c:73
char * pstrdup(const char *in)
Definition: mcxt.c:1759
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:81
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:76
Datum pg_lsn_ne(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:122
Datum pg_lsn_eq(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:113
Datum pg_lsn_cmp(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:186
#define MAXPG_LSNLEN
Definition: pg_lsn.c:21
Datum pg_lsn_out(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:75
Datum pg_lsn_smaller(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:176
Datum pg_lsn_send(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:97
#define MAXPG_LSNCOMPONENT
Definition: pg_lsn.c:22
Datum pg_lsn_le(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:149
Datum pg_lsn_in(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:64
Datum pg_lsn_pli(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:246
XLogRecPtr pg_lsn_in_safe(const char *str, Node *escontext)
Definition: pg_lsn.c:32
Datum pg_lsn_mii(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:280
Datum pg_lsn_hash(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:201
Datum pg_lsn_ge(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:158
Datum pg_lsn_hash_extended(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:208
Datum pg_lsn_gt(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:140
Datum pg_lsn_larger(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:167
Datum pg_lsn_recv(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:87
Datum pg_lsn_mi(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:219
Datum pg_lsn_lt(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:131
#define PG_GETARG_LSN(n)
Definition: pg_lsn.h:36
#define PG_RETURN_LSN(x)
Definition: pg_lsn.h:37
static char * buf
Definition: pg_test_fsync.c:72
void syntax_error(const char *source, int lineno, const char *line, const char *command, const char *msg, const char *more, int column)
Definition: pgbench.c:5626
#define snprintf
Definition: port.h:239
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
uint64_t Datum
Definition: postgres.h:70
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:360
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:222
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:326
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:453
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:346
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:152
struct StringInfoData * StringInfo
Definition: string.h:15
Definition: nodes.h:135
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:47
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28