PostgreSQL Source Code  git master
xid.c
Go to the documentation of this file.
1 /*-------------------------------------------------------------------------
2  *
3  * xid.c
4  * POSTGRES transaction identifier and command identifier datatypes.
5  *
6  * Portions Copyright (c) 1996-2022, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  * src/backend/utils/adt/xid.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16 
17 #include <limits.h>
18 
19 #include "access/multixact.h"
20 #include "access/transam.h"
21 #include "access/xact.h"
22 #include "libpq/pqformat.h"
23 #include "utils/builtins.h"
24 #include "utils/xid8.h"
25 
26 #define PG_GETARG_COMMANDID(n) DatumGetCommandId(PG_GETARG_DATUM(n))
27 #define PG_RETURN_COMMANDID(x) return CommandIdGetDatum(x)
28 
29 
30 Datum
32 {
33  char *str = PG_GETARG_CSTRING(0);
34 
35  PG_RETURN_TRANSACTIONID((TransactionId) strtoul(str, NULL, 0));
36 }
37 
38 Datum
40 {
41  TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
42  char *result = (char *) palloc(16);
43 
44  snprintf(result, 16, "%lu", (unsigned long) transactionId);
45  PG_RETURN_CSTRING(result);
46 }
47 
48 /*
49  * xidrecv - converts external binary format to xid
50  */
51 Datum
53 {
55 
57 }
58 
59 /*
60  * xidsend - converts xid to binary format
61  */
62 Datum
64 {
67 
69  pq_sendint32(&buf, arg1);
71 }
72 
73 /*
74  * xideq - are two xids equal?
75  */
76 Datum
78 {
81 
83 }
84 
85 /*
86  * xidneq - are two xids different?
87  */
88 Datum
90 {
93 
94  PG_RETURN_BOOL(!TransactionIdEquals(xid1, xid2));
95 }
96 
97 /*
98  * xid_age - compute age of an XID (relative to latest stable xid)
99  */
100 Datum
102 {
105 
106  /* Permanent XIDs are always infinitely old */
107  if (!TransactionIdIsNormal(xid))
108  PG_RETURN_INT32(INT_MAX);
109 
110  PG_RETURN_INT32((int32) (now - xid));
111 }
112 
113 /*
114  * mxid_age - compute age of a multi XID (relative to latest stable mxid)
115  */
116 Datum
118 {
121 
122  if (!MultiXactIdIsValid(xid))
123  PG_RETURN_INT32(INT_MAX);
124 
125  PG_RETURN_INT32((int32) (now - xid));
126 }
127 
128 /*
129  * xidComparator
130  * qsort comparison function for XIDs
131  *
132  * We can't use wraparound comparison for XIDs because that does not respect
133  * the triangle inequality! Any old sort order will do.
134  */
135 int
136 xidComparator(const void *arg1, const void *arg2)
137 {
138  TransactionId xid1 = *(const TransactionId *) arg1;
139  TransactionId xid2 = *(const TransactionId *) arg2;
140 
141  if (xid1 > xid2)
142  return 1;
143  if (xid1 < xid2)
144  return -1;
145  return 0;
146 }
147 
148 /*
149  * xidLogicalComparator
150  * qsort comparison function for XIDs
151  *
152  * This is used to compare only XIDs from the same epoch (e.g. for backends
153  * running at the same time). So there must be only normal XIDs, so there's
154  * no issue with triangle inequality.
155  */
156 int
157 xidLogicalComparator(const void *arg1, const void *arg2)
158 {
159  TransactionId xid1 = *(const TransactionId *) arg1;
160  TransactionId xid2 = *(const TransactionId *) arg2;
161 
164 
165  if (TransactionIdPrecedes(xid1, xid2))
166  return -1;
167 
168  if (TransactionIdPrecedes(xid2, xid1))
169  return 1;
170 
171  return 0;
172 }
173 
174 Datum
176 {
178 
180 }
181 
182 Datum
184 {
185  char *str = PG_GETARG_CSTRING(0);
186 
188 }
189 
190 Datum
192 {
194  char *result = (char *) palloc(21);
195 
196  snprintf(result, 21, UINT64_FORMAT, U64FromFullTransactionId(fxid));
197  PG_RETURN_CSTRING(result);
198 }
199 
200 Datum
202 {
204  uint64 value;
205 
206  value = (uint64) pq_getmsgint64(buf);
208 }
209 
210 Datum
212 {
215 
217  pq_sendint64(&buf, (uint64) U64FromFullTransactionId(arg1));
219 }
220 
221 Datum
223 {
226 
228 }
229 
230 Datum
232 {
235 
236  PG_RETURN_BOOL(!FullTransactionIdEquals(fxid1, fxid2));
237 }
238 
239 Datum
241 {
244 
246 }
247 
248 Datum
250 {
253 
255 }
256 
257 Datum
259 {
262 
264 }
265 
266 Datum
268 {
271 
273 }
274 
275 Datum
277 {
280 
281  if (FullTransactionIdFollows(fxid1, fxid2))
282  PG_RETURN_INT32(1);
283  else if (FullTransactionIdEquals(fxid1, fxid2))
284  PG_RETURN_INT32(0);
285  else
286  PG_RETURN_INT32(-1);
287 }
288 
289 Datum
291 {
294 
295  if (FullTransactionIdFollows(fxid1, fxid2))
297  else
299 }
300 
301 Datum
303 {
306 
307  if (FullTransactionIdPrecedes(fxid1, fxid2))
309  else
311 }
312 
313 /*****************************************************************************
314  * COMMAND IDENTIFIER ROUTINES *
315  *****************************************************************************/
316 
317 /*
318  * cidin - converts CommandId to internal representation.
319  */
320 Datum
322 {
323  char *str = PG_GETARG_CSTRING(0);
324 
325  PG_RETURN_COMMANDID((CommandId) strtoul(str, NULL, 0));
326 }
327 
328 /*
329  * cidout - converts a cid to external representation.
330  */
331 Datum
333 {
335  char *result = (char *) palloc(16);
336 
337  snprintf(result, 16, "%lu", (unsigned long) c);
338  PG_RETURN_CSTRING(result);
339 }
340 
341 /*
342  * cidrecv - converts external binary format to cid
343  */
344 Datum
346 {
348 
350 }
351 
352 /*
353  * cidsend - converts cid to binary format
354  */
355 Datum
357 {
358  CommandId arg1 = PG_GETARG_COMMANDID(0);
360 
362  pq_sendint32(&buf, arg1);
364 }
365 
366 Datum
368 {
369  CommandId arg1 = PG_GETARG_COMMANDID(0);
370  CommandId arg2 = PG_GETARG_COMMANDID(1);
371 
372  PG_RETURN_BOOL(arg1 == arg2);
373 }
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1538
signed int int32
Definition: c.h:429
TransactionId MultiXactId
Definition: c.h:597
#define UINT64_FORMAT
Definition: c.h:484
#define strtou64(str, endptr, base)
Definition: c.h:1322
uint32 CommandId
Definition: c.h:601
uint32 TransactionId
Definition: c.h:587
#define PG_RETURN_BYTEA_P(x)
Definition: fmgr.h:371
#define PG_GETARG_POINTER(n)
Definition: fmgr.h:276
#define PG_RETURN_CSTRING(x)
Definition: fmgr.h:362
#define PG_GETARG_CSTRING(n)
Definition: fmgr.h:277
#define PG_RETURN_TRANSACTIONID(x)
Definition: fmgr.h:364
#define PG_GETARG_TRANSACTIONID(n)
Definition: fmgr.h:279
#define PG_RETURN_INT32(x)
Definition: fmgr.h:354
#define PG_FUNCTION_ARGS
Definition: fmgr.h:193
#define PG_RETURN_BOOL(x)
Definition: fmgr.h:359
static struct @151 value
Assert(fmt[strlen(fmt) - 1] !='\n')
void * palloc(Size size)
Definition: mcxt.c:1068
MultiXactId ReadNextMultiXactId(void)
Definition: multixact.c:723
#define MultiXactIdIsValid(multi)
Definition: multixact.h:28
static char * buf
Definition: pg_test_fsync.c:67
#define snprintf
Definition: port.h:225
uintptr_t Datum
Definition: postgres.h:411
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:417
void pq_begintypsend(StringInfo buf)
Definition: pqformat.c:328
int64 pq_getmsgint64(StringInfo msg)
Definition: pqformat.c:455
bytea * pq_endtypsend(StringInfo buf)
Definition: pqformat.c:348
static void pq_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:145
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:153
char * c
StringInfoData * StringInfo
Definition: stringinfo.h:44
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:300
#define FullTransactionIdEquals(a, b)
Definition: transam.h:50
#define FullTransactionIdPrecedesOrEquals(a, b)
Definition: transam.h:52
#define U64FromFullTransactionId(x)
Definition: transam.h:49
static FullTransactionId FullTransactionIdFromU64(uint64 value)
Definition: transam.h:81
#define FullTransactionIdFollowsOrEquals(a, b)
Definition: transam.h:54
#define TransactionIdEquals(id1, id2)
Definition: transam.h:43
#define FullTransactionIdFollows(a, b)
Definition: transam.h:53
#define XidFromFullTransactionId(x)
Definition: transam.h:48
#define TransactionIdIsNormal(xid)
Definition: transam.h:42
#define FullTransactionIdPrecedes(a, b)
Definition: transam.h:51
TransactionId GetStableLatestTransactionId(void)
Definition: xact.c:594
#define PG_GETARG_FULLTRANSACTIONID(X)
Definition: xid8.h:19
#define PG_RETURN_FULLTRANSACTIONID(X)
Definition: xid8.h:20
#define PG_RETURN_COMMANDID(x)
Definition: xid.c:27
Datum xidneq(PG_FUNCTION_ARGS)
Definition: xid.c:89
#define PG_GETARG_COMMANDID(n)
Definition: xid.c:26
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:136
Datum xid8ge(PG_FUNCTION_ARGS)
Definition: xid.c:267
Datum cidin(PG_FUNCTION_ARGS)
Definition: xid.c:321
Datum xideq(PG_FUNCTION_ARGS)
Definition: xid.c:77
Datum cidout(PG_FUNCTION_ARGS)
Definition: xid.c:332
Datum xid_age(PG_FUNCTION_ARGS)
Definition: xid.c:101
Datum xid8toxid(PG_FUNCTION_ARGS)
Definition: xid.c:175
Datum xidrecv(PG_FUNCTION_ARGS)
Definition: xid.c:52
Datum xid8_larger(PG_FUNCTION_ARGS)
Definition: xid.c:290
int xidLogicalComparator(const void *arg1, const void *arg2)
Definition: xid.c:157
Datum xid8eq(PG_FUNCTION_ARGS)
Definition: xid.c:222
Datum xid8in(PG_FUNCTION_ARGS)
Definition: xid.c:183
Datum xid8_smaller(PG_FUNCTION_ARGS)
Definition: xid.c:302
Datum xid8cmp(PG_FUNCTION_ARGS)
Definition: xid.c:276
Datum cideq(PG_FUNCTION_ARGS)
Definition: xid.c:367
Datum xid8send(PG_FUNCTION_ARGS)
Definition: xid.c:211
Datum xid8gt(PG_FUNCTION_ARGS)
Definition: xid.c:249
Datum xidin(PG_FUNCTION_ARGS)
Definition: xid.c:31
Datum cidrecv(PG_FUNCTION_ARGS)
Definition: xid.c:345
Datum xid8lt(PG_FUNCTION_ARGS)
Definition: xid.c:240
Datum xidsend(PG_FUNCTION_ARGS)
Definition: xid.c:63
Datum xid8ne(PG_FUNCTION_ARGS)
Definition: xid.c:231
Datum xid8le(PG_FUNCTION_ARGS)
Definition: xid.c:258
Datum xid8recv(PG_FUNCTION_ARGS)
Definition: xid.c:201
Datum mxid_age(PG_FUNCTION_ARGS)
Definition: xid.c:117
Datum cidsend(PG_FUNCTION_ARGS)
Definition: xid.c:356
Datum xid8out(PG_FUNCTION_ARGS)
Definition: xid.c:191
Datum xidout(PG_FUNCTION_ARGS)
Definition: xid.c:39