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-2021, 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 
30 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  *have_error = false;
40 
41  /* Sanity check input format. */
42  len1 = strspn(str, "0123456789abcdefABCDEF");
43  if (len1 < 1 || len1 > MAXPG_LSNCOMPONENT || str[len1] != '/')
44  {
45  *have_error = true;
46  return InvalidXLogRecPtr;
47  }
48  len2 = strspn(str + len1 + 1, "0123456789abcdefABCDEF");
49  if (len2 < 1 || len2 > MAXPG_LSNCOMPONENT || str[len1 + 1 + len2] != '\0')
50  {
51  *have_error = true;
52  return InvalidXLogRecPtr;
53  }
54 
55  /* Decode result. */
56  id = (uint32) strtoul(str, NULL, 16);
57  off = (uint32) strtoul(str + len1 + 1, NULL, 16);
58  result = ((uint64) id << 32) | off;
59 
60  return result;
61 }
62 
63 Datum
65 {
66  char *str = PG_GETARG_CSTRING(0);
67  XLogRecPtr result;
68  bool have_error = false;
69 
70  result = pg_lsn_in_internal(str, &have_error);
71  if (have_error)
72  ereport(ERROR,
73  (errcode(ERRCODE_INVALID_TEXT_REPRESENTATION),
74  errmsg("invalid input syntax for type %s: \"%s\"",
75  "pg_lsn", str)));
76 
77  PG_RETURN_LSN(result);
78 }
79 
80 Datum
82 {
83  XLogRecPtr lsn = PG_GETARG_LSN(0);
84  char buf[MAXPG_LSNLEN + 1];
85  char *result;
86 
87  snprintf(buf, sizeof buf, "%X/%X", LSN_FORMAT_ARGS(lsn));
88  result = pstrdup(buf);
89  PG_RETURN_CSTRING(result);
90 }
91 
92 Datum
94 {
96  XLogRecPtr result;
97 
98  result = pq_getmsgint64(buf);
99  PG_RETURN_LSN(result);
100 }
101 
102 Datum
104 {
105  XLogRecPtr lsn = PG_GETARG_LSN(0);
107 
108  pq_begintypsend(&buf);
109  pq_sendint64(&buf, lsn);
111 }
112 
113 
114 /*----------------------------------------------------------
115  * Operators for PostgreSQL LSNs
116  *---------------------------------------------------------*/
117 
118 Datum
120 {
121  XLogRecPtr lsn1 = PG_GETARG_LSN(0);
122  XLogRecPtr lsn2 = PG_GETARG_LSN(1);
123 
124  PG_RETURN_BOOL(lsn1 == lsn2);
125 }
126 
127 Datum
129 {
130  XLogRecPtr lsn1 = PG_GETARG_LSN(0);
131  XLogRecPtr lsn2 = PG_GETARG_LSN(1);
132 
133  PG_RETURN_BOOL(lsn1 != lsn2);
134 }
135 
136 Datum
138 {
139  XLogRecPtr lsn1 = PG_GETARG_LSN(0);
140  XLogRecPtr lsn2 = PG_GETARG_LSN(1);
141 
142  PG_RETURN_BOOL(lsn1 < lsn2);
143 }
144 
145 Datum
147 {
148  XLogRecPtr lsn1 = PG_GETARG_LSN(0);
149  XLogRecPtr lsn2 = PG_GETARG_LSN(1);
150 
151  PG_RETURN_BOOL(lsn1 > lsn2);
152 }
153 
154 Datum
156 {
157  XLogRecPtr lsn1 = PG_GETARG_LSN(0);
158  XLogRecPtr lsn2 = PG_GETARG_LSN(1);
159 
160  PG_RETURN_BOOL(lsn1 <= lsn2);
161 }
162 
163 Datum
165 {
166  XLogRecPtr lsn1 = PG_GETARG_LSN(0);
167  XLogRecPtr lsn2 = PG_GETARG_LSN(1);
168 
169  PG_RETURN_BOOL(lsn1 >= lsn2);
170 }
171 
172 Datum
174 {
175  XLogRecPtr lsn1 = PG_GETARG_LSN(0);
176  XLogRecPtr lsn2 = PG_GETARG_LSN(1);
177 
178  PG_RETURN_LSN((lsn1 > lsn2) ? lsn1 : lsn2);
179 }
180 
181 Datum
183 {
184  XLogRecPtr lsn1 = PG_GETARG_LSN(0);
185  XLogRecPtr lsn2 = PG_GETARG_LSN(1);
186 
187  PG_RETURN_LSN((lsn1 < lsn2) ? lsn1 : lsn2);
188 }
189 
190 /* btree index opclass support */
191 Datum
193 {
194  XLogRecPtr a = PG_GETARG_LSN(0);
195  XLogRecPtr b = PG_GETARG_LSN(1);
196 
197  if (a > b)
198  PG_RETURN_INT32(1);
199  else if (a == b)
200  PG_RETURN_INT32(0);
201  else
202  PG_RETURN_INT32(-1);
203 }
204 
205 /* hash index opclass support */
206 Datum
208 {
209  /* We can use hashint8 directly */
210  return hashint8(fcinfo);
211 }
212 
213 Datum
215 {
216  return hashint8extended(fcinfo);
217 }
218 
219 
220 /*----------------------------------------------------------
221  * Arithmetic operators on PostgreSQL LSNs.
222  *---------------------------------------------------------*/
223 
224 Datum
226 {
227  XLogRecPtr lsn1 = PG_GETARG_LSN(0);
228  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  if (lsn1 < lsn2)
234  snprintf(buf, sizeof buf, "-" UINT64_FORMAT, lsn2 - lsn1);
235  else
236  snprintf(buf, sizeof buf, UINT64_FORMAT, lsn1 - lsn2);
237 
238  /* Convert to numeric. */
240  CStringGetDatum(buf),
241  ObjectIdGetDatum(0),
242  Int32GetDatum(-1));
243 
244  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
253 {
254  XLogRecPtr lsn = PG_GETARG_LSN(0);
255  Numeric nbytes = PG_GETARG_NUMERIC(1);
256  Datum num;
257  Datum res;
258  char buf[32];
259 
260  if (numeric_is_nan(nbytes))
261  ereport(ERROR,
262  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
263  errmsg("cannot add NaN to pg_lsn")));
264 
265  /* Convert to numeric */
266  snprintf(buf, sizeof(buf), UINT64_FORMAT, lsn);
268  CStringGetDatum(buf),
269  ObjectIdGetDatum(0),
270  Int32GetDatum(-1));
271 
272  /* Add two numerics */
274  NumericGetDatum(num),
275  NumericGetDatum(nbytes));
276 
277  /* Convert to pg_lsn */
278  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
287 {
288  XLogRecPtr lsn = PG_GETARG_LSN(0);
289  Numeric nbytes = PG_GETARG_NUMERIC(1);
290  Datum num;
291  Datum res;
292  char buf[32];
293 
294  if (numeric_is_nan(nbytes))
295  ereport(ERROR,
296  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
297  errmsg("cannot subtract NaN from pg_lsn")));
298 
299  /* Convert to numeric */
300  snprintf(buf, sizeof(buf), UINT64_FORMAT, lsn);
302  CStringGetDatum(buf),
303  ObjectIdGetDatum(0),
304  Int32GetDatum(-1));
305 
306  /* Subtract two numerics */
308  NumericGetDatum(num),
309  NumericGetDatum(nbytes));
310 
311  /* Convert to pg_lsn */
312  return DirectFunctionCall1(numeric_pg_lsn, res);
313 }
#define MAXPG_LSNLEN
Definition: pg_lsn.c:22
#define InvalidXLogRecPtr
Definition: xlogdefs.h:28
Datum pg_lsn_le(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:155
Datum hashint8(PG_FUNCTION_ARGS)
Definition: hashfunc.c:83
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
Datum pg_lsn_mi(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:225
char * pstrdup(const char *in)
Definition: mcxt.c:1299
#define NumericGetDatum(X)
Definition: numeric.h:51
Datum pg_lsn_hash_extended(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:214
StringInfoData * StringInfo
Definition: stringinfo.h:44
Datum pg_lsn_send(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:103
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
Datum pg_lsn_pli(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:252
int errcode(int sqlerrcode)
Definition: elog.c:698
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define DirectFunctionCall1(func, arg1)
Definition: fmgr.h:626
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
Datum hashint8extended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:103
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:153
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
Datum pg_lsn_in(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:64
#define PG_RETURN_LSN(x)
Definition: pg_lsn.h:25
Datum pg_lsn_smaller(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:182
#define LSN_FORMAT_ARGS(lsn)
Definition: xlogdefs.h:43
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define ERROR
Definition: elog.h:46
bool numeric_is_nan(Numeric num)
Definition: numeric.c:774
Datum pg_lsn_mii(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:286
Datum pg_lsn_recv(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:93
Datum numeric_pg_lsn(PG_FUNCTION_ARGS)
Definition: numeric.c:4488
static char * buf
Definition: pg_test_fsync.c:68
#define CStringGetDatum(X)
Definition: postgres.h:622
unsigned int uint32
Definition: c.h:441
Datum pg_lsn_ge(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:164
Datum numeric_in(PG_FUNCTION_ARGS)
Definition: numeric.c:621
Datum pg_lsn_eq(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:119
#define DirectFunctionCall3(func, arg1, arg2, arg3)
Definition: fmgr.h:630
Datum pg_lsn_gt(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:146
#define PG_GETARG_LSN(n)
Definition: pg_lsn.h:24
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
uintptr_t Datum
Definition: postgres.h:411
Datum numeric_sub(PG_FUNCTION_ARGS)
Definition: numeric.c:2788
Datum pg_lsn_out(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:81
#define ereport(elevel,...)
Definition: elog.h:157
XLogRecPtr pg_lsn_in_internal(const char *str, bool *have_error)
Definition: pg_lsn.c:30
#define PG_GETARG_NUMERIC(n)
Definition: numeric.h:52
uint64 XLogRecPtr
Definition: xlogdefs.h:21
#define Assert(condition)
Definition: c.h:804
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
Datum pg_lsn_lt(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:137
#define Int32GetDatum(X)
Definition: postgres.h:523
int errmsg(const char *fmt,...)
Definition: elog.c:909
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:455
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
Datum pg_lsn_cmp(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:192
#define MAXPG_LSNCOMPONENT
Definition: pg_lsn.c:23
Datum pg_lsn_hash(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:207
#define snprintf
Definition: port.h:216
Datum numeric_add(PG_FUNCTION_ARGS)
Definition: numeric.c:2711
#define UINT64_FORMAT
Definition: c.h:484
Datum pg_lsn_larger(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:173
#define DirectFunctionCall2(func, arg1, arg2)
Definition: fmgr.h:628
Datum pg_lsn_ne(PG_FUNCTION_ARGS)
Definition: pg_lsn.c:128