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
29pg_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 *have_error = false;
39
40 /* Sanity check input format. */
41 len1 = strspn(str, "0123456789abcdefABCDEF");
42 if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/')
43 {
44 *have_error = true;
45 return InvalidXLogRecPtr;
46 }
47 len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF");
48 if (len2 < 1 || len2 > MAXPG_LSNCOMPONENT || str[len1 + 1 + len2] != '\0')
49 {
50 *have_error = true;
51 return InvalidXLogRecPtr;
52 }
53
54 /* Decode result. */
55 id = (uint32) strtoul(str, NULL, 16);
56 off = (uint32) strtoul(str + len1 + 1, NULL, 16);
57 result = ((uint64) id << 32) | off;
58
59 return result;
60}
61
64{
65 char *str = PG_GETARG_CSTRING(0);
66 XLogRecPtr result;
67 bool have_error = false;
68
69 result = pg_lsn_in_internal(str, &have_error);
70 if (have_error)
71 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 PG_RETURN_LSN(result);
77}
78
81{
83 char buf[MAXPG_LSNLEN + 1];
84 char *result;
85
86 snprintf(buf, sizeof buf, "%X/%X", LSN_FORMAT_ARGS(lsn));
87 result = pstrdup(buf);
88 PG_RETURN_CSTRING(result);
89}
90
93{
95 XLogRecPtr result;
96
97 result = pq_getmsgint64(buf);
98 PG_RETURN_LSN(result);
99}
100
101Datum
103{
104 XLogRecPtr lsn = PG_GETARG_LSN(0);
106
108 pq_sendint64(&buf, lsn);
110}
111
112
113/*----------------------------------------------------------
114 * Operators for PostgreSQL LSNs
115 *---------------------------------------------------------*/
116
117Datum
119{
120 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
121 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
122
123 PG_RETURN_BOOL(lsn1 == lsn2);
124}
125
126Datum
128{
129 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
130 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
131
132 PG_RETURN_BOOL(lsn1 != lsn2);
133}
134
135Datum
137{
138 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
139 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
140
141 PG_RETURN_BOOL(lsn1 < lsn2);
142}
143
144Datum
146{
147 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
148 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
149
150 PG_RETURN_BOOL(lsn1 > lsn2);
151}
152
153Datum
155{
156 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
157 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
158
159 PG_RETURN_BOOL(lsn1 <= lsn2);
160}
161
162Datum
164{
165 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
166 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
167
168 PG_RETURN_BOOL(lsn1 >= lsn2);
169}
170
171Datum
173{
174 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
175 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
176
177 PG_RETURN_LSN((lsn1 > lsn2) ? lsn1 : lsn2);
178}
179
180Datum
182{
183 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
184 XLogRecPtr lsn2 = PG_GETARG_LSN(1);
185
186 PG_RETURN_LSN((lsn1 < lsn2) ? lsn1 : lsn2);
187}
188
189/* btree index opclass support */
190Datum
192{
195
196 if (a > b)
198 else if (a == b)
200 else
201 PG_RETURN_INT32(-1);
202}
203
204/* hash index opclass support */
205Datum
207{
208 /* We can use hashint8 directly */
209 return hashint8(fcinfo);
210}
211
212Datum
214{
215 return hashint8extended(fcinfo);
216}
217
218
219/*----------------------------------------------------------
220 * Arithmetic operators on PostgreSQL LSNs.
221 *---------------------------------------------------------*/
222
223Datum
225{
226 XLogRecPtr lsn1 = PG_GETARG_LSN(0);
227 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 if (lsn1 < lsn2)
233 snprintf(buf, sizeof buf, "-" UINT64_FORMAT, lsn2 - lsn1);
234 else
235 snprintf(buf, sizeof buf, UINT64_FORMAT, lsn1 - lsn2);
236
237 /* Convert to numeric. */
241 Int32GetDatum(-1));
242
243 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 */
250Datum
252{
253 XLogRecPtr lsn = PG_GETARG_LSN(0);
254 Numeric nbytes = PG_GETARG_NUMERIC(1);
255 Datum num;
256 Datum res;
257 char buf[32];
258
259 if (numeric_is_nan(nbytes))
261 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
262 errmsg("cannot add NaN to pg_lsn")));
263
264 /* Convert to numeric */
265 snprintf(buf, sizeof(buf), UINT64_FORMAT, lsn);
269 Int32GetDatum(-1));
270
271 /* Add two numerics */
273 num,
274 NumericGetDatum(nbytes));
275
276 /* Convert to pg_lsn */
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 */
284Datum
286{
287 XLogRecPtr lsn = PG_GETARG_LSN(0);
288 Numeric nbytes = PG_GETARG_NUMERIC(1);
289 Datum num;
290 Datum res;
291 char buf[32];
292
293 if (numeric_is_nan(nbytes))
295 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
296 errmsg("cannot subtract NaN from pg_lsn")));
297
298 /* Convert to numeric */
299 snprintf(buf, sizeof(buf), UINT64_FORMAT, lsn);
303 Int32GetDatum(-1));
304
305 /* Subtract two numerics */
307 num,
308 NumericGetDatum(nbytes));
309
310 /* Convert to pg_lsn */
312}
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition: numeric.c:3043
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:637
bool numeric_is_nan(Numeric num)
Definition: numeric.c:851
Datum numeric_add(PG_FUNCTION_ARGS)
Definition: numeric.c:2966
Datum numeric_pg_lsn(PG_FUNCTION_ARGS)
Definition: numeric.c:4868
#define Assert(condition)
Definition: c.h:815
#define UINT64_FORMAT
Definition: c.h:507
uint64_t uint64
Definition: c.h:489
uint32_t uint32
Definition: c.h:488
int errcode(int sqlerrcode)
Definition: elog.c:853
int errmsg(const char *fmt,...)
Definition: elog.c:1070
#define ereturn(context, dummy_value,...)
Definition: elog.h:277
#define ERROR
Definition: elog.h:39
#define ereport(elevel,...)
Definition: elog.h:149
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:643
#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:641
#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:645
#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:69
int a
Definition: isn.c:68
char * pstrdup(const char *in)
Definition: mcxt.c:1696
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:78
static Datum NumericGetDatum(Numeric X)
Definition: numeric.h:73
Datum pg_lsn_ne(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:127
Datum pg_lsn_eq(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:118
Datum pg_lsn_cmp(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:191
#define MAXPG_LSNLEN
Definition: pg_lsn.c:21
Datum pg_lsn_out(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:80
Datum pg_lsn_smaller(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:181
Datum pg_lsn_send(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:102
XLogRecPtr pg_lsn_in_internal(const char *str, bool *have_error)
Definition: pg_lsn.c:29
#define MAXPG_LSNCOMPONENT
Definition: pg_lsn.c:22
Datum pg_lsn_le(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:154
Datum pg_lsn_in(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:63
Datum pg_lsn_pli(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:251
Datum pg_lsn_mii(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:285
Datum pg_lsn_hash(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:206
Datum pg_lsn_ge(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:163
Datum pg_lsn_hash_extended(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:213
Datum pg_lsn_gt(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:145
Datum pg_lsn_larger(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:172
Datum pg_lsn_recv(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:92
Datum pg_lsn_mi(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:224
Datum pg_lsn_lt(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:136
#define PG_GETARG_LSN(n)
Definition: pg_lsn.h:33
#define PG_RETURN_LSN(x)
Definition: pg_lsn.h:34
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:239
uintptr_t Datum
Definition: postgres.h:69
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:257
static Datum CStringGetDatum(const char *X)
Definition: postgres.h:355
static Datum Int32GetDatum(int32 X)
Definition: postgres.h:217
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
StringInfoData * StringInfo
Definition: stringinfo.h:54
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28