PostgreSQL Source Code: src/backend/utils/adt/pg_lsn.c Source File

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 */
31XLogRecPtr
32 pg_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
56syntax_error:
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
63Datum
64 pg_lsn_in(PG_FUNCTION_ARGS)
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
74Datum
75 pg_lsn_out(PG_FUNCTION_ARGS)
76{
77 XLogRecPtr lsn = PG_GETARG_LSN(0);
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
86Datum
87 pg_lsn_recv(PG_FUNCTION_ARGS)
88{
89 StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
90 XLogRecPtr result;
91
92 result = pq_getmsgint64(buf);
93 PG_RETURN_LSN(result);
94}
95
96Datum
97 pg_lsn_send(PG_FUNCTION_ARGS)
98{
99 XLogRecPtr lsn = PG_GETARG_LSN(0);
100 StringInfoData buf;
101
102 pq_begintypsend(&buf);
103 pq_sendint64(&buf, lsn);
104 PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
105}
106
107
108/*----------------------------------------------------------
109 * Operators for PostgreSQL LSNs
110 *---------------------------------------------------------*/
111
112Datum
113 pg_lsn_eq(PG_FUNCTION_ARGS)
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
122 pg_lsn_ne(PG_FUNCTION_ARGS)
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
131 pg_lsn_lt(PG_FUNCTION_ARGS)
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
140 pg_lsn_gt(PG_FUNCTION_ARGS)
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
149 pg_lsn_le(PG_FUNCTION_ARGS)
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
158 pg_lsn_ge(PG_FUNCTION_ARGS)
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
167 pg_lsn_larger(PG_FUNCTION_ARGS)
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
176 pg_lsn_smaller(PG_FUNCTION_ARGS)
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
186 pg_lsn_cmp(PG_FUNCTION_ARGS)
187{
188 XLogRecPtr a = PG_GETARG_LSN(0);
189 XLogRecPtr b = PG_GETARG_LSN(1);
190
191 if (a > b)
192 PG_RETURN_INT32(1);
193 else if (a == b)
194 PG_RETURN_INT32(0);
195 else
196 PG_RETURN_INT32(-1);
197}
198
199/* hash index opclass support */
200Datum
201 pg_lsn_hash(PG_FUNCTION_ARGS)
202{
203 /* We can use hashint8 directly */
204 return hashint8(fcinfo);
205}
206
207Datum
208 pg_lsn_hash_extended(PG_FUNCTION_ARGS)
209{
210 return hashint8extended(fcinfo);
211}
212
213
214/*----------------------------------------------------------
215 * Arithmetic operators on PostgreSQL LSNs.
216 *---------------------------------------------------------*/
217
218Datum
219 pg_lsn_mi(PG_FUNCTION_ARGS)
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. */
233 result = DirectFunctionCall3(numeric_in,
234 CStringGetDatum(buf),
235 ObjectIdGetDatum(0),
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
246 pg_lsn_pli(PG_FUNCTION_ARGS)
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))
255 ereport(ERROR,
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);
261 num = DirectFunctionCall3(numeric_in,
262 CStringGetDatum(buf),
263 ObjectIdGetDatum(0),
264 Int32GetDatum(-1));
265
266 /* Add two numerics */
267 res = DirectFunctionCall2(numeric_add,
268 num,
269 NumericGetDatum(nbytes));
270
271 /* Convert to pg_lsn */
272 return DirectFunctionCall1(numeric_pg_lsn, res);
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
280 pg_lsn_mii(PG_FUNCTION_ARGS)
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))
289 ereport(ERROR,
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);
295 num = DirectFunctionCall3(numeric_in,
296 CStringGetDatum(buf),
297 ObjectIdGetDatum(0),
298 Int32GetDatum(-1));
299
300 /* Subtract two numerics */
301 res = DirectFunctionCall2(numeric_sub,
302 num,
303 NumericGetDatum(nbytes));
304
305 /* Convert to pg_lsn */
306 return DirectFunctionCall1(numeric_pg_lsn, res);
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:557
uint64_t uint64
Definition: c.h:539
uint32_t uint32
Definition: c.h:538
int errcode(int sqlerrcode)
Definition: elog.c:854
int errmsg(const char *fmt,...)
Definition: elog.c:1071
#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
b
int b
Definition: isn.c:74
a
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:5551
#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:46
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28

AltStyle によって変換されたページ (->オリジナル) /