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-2024, 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 "common/hashfn.h"
23 #include "common/int.h"
24 #include "libpq/pqformat.h"
25 #include "utils/builtins.h"
26 #include "utils/xid8.h"
27 
28 #define PG_GETARG_COMMANDID(n) DatumGetCommandId(PG_GETARG_DATUM(n))
29 #define PG_RETURN_COMMANDID(x) return CommandIdGetDatum(x)
30 
31 
32 Datum
34 {
35  char *str = PG_GETARG_CSTRING(0);
36  TransactionId result;
37 
38  result = uint32in_subr(str, NULL, "xid", fcinfo->context);
40 }
41 
42 Datum
44 {
45  TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
46  char *result = (char *) palloc(16);
47 
48  snprintf(result, 16, "%lu", (unsigned long) transactionId);
49  PG_RETURN_CSTRING(result);
50 }
51 
52 /*
53  * xidrecv - converts external binary format to xid
54  */
55 Datum
57 {
59 
61 }
62 
63 /*
64  * xidsend - converts xid to binary format
65  */
66 Datum
68 {
71 
73  pq_sendint32(&buf, arg1);
75 }
76 
77 /*
78  * xideq - are two xids equal?
79  */
80 Datum
82 {
85 
87 }
88 
89 /*
90  * xidneq - are two xids different?
91  */
92 Datum
94 {
97 
98  PG_RETURN_BOOL(!TransactionIdEquals(xid1, xid2));
99 }
100 
101 Datum
103 {
105 }
106 
107 Datum
109 {
111 }
112 
113 /*
114  * xid_age - compute age of an XID (relative to latest stable xid)
115  */
116 Datum
118 {
121 
122  /* Permanent XIDs are always infinitely old */
123  if (!TransactionIdIsNormal(xid))
124  PG_RETURN_INT32(INT_MAX);
125 
126  PG_RETURN_INT32((int32) (now - xid));
127 }
128 
129 /*
130  * mxid_age - compute age of a multi XID (relative to latest stable mxid)
131  */
132 Datum
134 {
137 
138  if (!MultiXactIdIsValid(xid))
139  PG_RETURN_INT32(INT_MAX);
140 
141  PG_RETURN_INT32((int32) (now - xid));
142 }
143 
144 /*
145  * xidComparator
146  * qsort comparison function for XIDs
147  *
148  * We can't use wraparound comparison for XIDs because that does not respect
149  * the triangle inequality! Any old sort order will do.
150  */
151 int
152 xidComparator(const void *arg1, const void *arg2)
153 {
154  TransactionId xid1 = *(const TransactionId *) arg1;
155  TransactionId xid2 = *(const TransactionId *) arg2;
156 
157  return pg_cmp_u32(xid1, xid2);
158 }
159 
160 /*
161  * xidLogicalComparator
162  * qsort comparison function for XIDs
163  *
164  * This is used to compare only XIDs from the same epoch (e.g. for backends
165  * running at the same time). So there must be only normal XIDs, so there's
166  * no issue with triangle inequality.
167  */
168 int
169 xidLogicalComparator(const void *arg1, const void *arg2)
170 {
171  TransactionId xid1 = *(const TransactionId *) arg1;
172  TransactionId xid2 = *(const TransactionId *) arg2;
173 
176 
177  if (TransactionIdPrecedes(xid1, xid2))
178  return -1;
179 
180  if (TransactionIdPrecedes(xid2, xid1))
181  return 1;
182 
183  return 0;
184 }
185 
186 Datum
188 {
190 
192 }
193 
194 Datum
196 {
197  char *str = PG_GETARG_CSTRING(0);
198  uint64 result;
199 
200  result = uint64in_subr(str, NULL, "xid8", fcinfo->context);
202 }
203 
204 Datum
206 {
208  char *result = (char *) palloc(21);
209 
210  snprintf(result, 21, UINT64_FORMAT, U64FromFullTransactionId(fxid));
211  PG_RETURN_CSTRING(result);
212 }
213 
214 Datum
216 {
218  uint64 value;
219 
220  value = (uint64) pq_getmsgint64(buf);
222 }
223 
224 Datum
226 {
229 
231  pq_sendint64(&buf, (uint64) U64FromFullTransactionId(arg1));
233 }
234 
235 Datum
237 {
240 
242 }
243 
244 Datum
246 {
249 
250  PG_RETURN_BOOL(!FullTransactionIdEquals(fxid1, fxid2));
251 }
252 
253 Datum
255 {
258 
260 }
261 
262 Datum
264 {
267 
269 }
270 
271 Datum
273 {
276 
278 }
279 
280 Datum
282 {
285 
287 }
288 
289 Datum
291 {
294 
295  if (FullTransactionIdFollows(fxid1, fxid2))
296  PG_RETURN_INT32(1);
297  else if (FullTransactionIdEquals(fxid1, fxid2))
298  PG_RETURN_INT32(0);
299  else
300  PG_RETURN_INT32(-1);
301 }
302 
303 Datum
305 {
306  return hashint8(fcinfo);
307 }
308 
309 Datum
311 {
312  return hashint8extended(fcinfo);
313 }
314 
315 Datum
317 {
320 
321  if (FullTransactionIdFollows(fxid1, fxid2))
323  else
325 }
326 
327 Datum
329 {
332 
333  if (FullTransactionIdPrecedes(fxid1, fxid2))
335  else
337 }
338 
339 /*****************************************************************************
340  * COMMAND IDENTIFIER ROUTINES *
341  *****************************************************************************/
342 
343 /*
344  * cidin - converts CommandId to internal representation.
345  */
346 Datum
348 {
349  char *str = PG_GETARG_CSTRING(0);
350  CommandId result;
351 
352  result = uint32in_subr(str, NULL, "cid", fcinfo->context);
353  PG_RETURN_COMMANDID(result);
354 }
355 
356 /*
357  * cidout - converts a cid to external representation.
358  */
359 Datum
361 {
363  char *result = (char *) palloc(16);
364 
365  snprintf(result, 16, "%lu", (unsigned long) c);
366  PG_RETURN_CSTRING(result);
367 }
368 
369 /*
370  * cidrecv - converts external binary format to cid
371  */
372 Datum
374 {
376 
378 }
379 
380 /*
381  * cidsend - converts cid to binary format
382  */
383 Datum
385 {
386  CommandId arg1 = PG_GETARG_COMMANDID(0);
388 
390  pq_sendint32(&buf, arg1);
392 }
393 
394 Datum
396 {
397  CommandId arg1 = PG_GETARG_COMMANDID(0);
398  CommandId arg2 = PG_GETARG_COMMANDID(1);
399 
400  PG_RETURN_BOOL(arg1 == arg2);
401 }
402 
403 Datum
405 {
406  return hash_uint32(PG_GETARG_COMMANDID(0));
407 }
408 
409 Datum
411 {
413 }
Datum now(PG_FUNCTION_ARGS)
Definition: timestamp.c:1608
signed int int32
Definition: c.h:496
#define Assert(condition)
Definition: c.h:849
TransactionId MultiXactId
Definition: c.h:653
#define UINT64_FORMAT
Definition: c.h:540
uint32 CommandId
Definition: c.h:657
uint32 TransactionId
Definition: c.h:643
#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_GETARG_INT64(n)
Definition: fmgr.h:283
#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 Datum hash_uint32(uint32 k)
Definition: hashfn.h:43
static Datum hash_uint32_extended(uint32 k, uint64 seed)
Definition: hashfn.h:49
const char * str
Datum hashint8extended(PG_FUNCTION_ARGS)
Definition: hashfunc.c:103
Datum hashint8(PG_FUNCTION_ARGS)
Definition: hashfunc.c:83
static struct @157 value
static int pg_cmp_u32(uint32 a, uint32 b)
Definition: int.h:604
void * palloc(Size size)
Definition: mcxt.c:1317
MultiXactId ReadNextMultiXactId(void)
Definition: multixact.c:771
#define MultiXactIdIsValid(multi)
Definition: multixact.h:28
uint64 uint64in_subr(const char *s, char **endloc, const char *typname, Node *escontext)
Definition: numutils.c:985
uint32 uint32in_subr(const char *s, char **endloc, const char *typname, Node *escontext)
Definition: numutils.c:898
static char * buf
Definition: pg_test_fsync.c:73
#define snprintf
Definition: port.h:238
uintptr_t Datum
Definition: postgres.h:64
unsigned int pq_getmsgint(StringInfo msg, int b)
Definition: pqformat.c:415
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_sendint32(StringInfo buf, uint32 i)
Definition: pqformat.h:144
static void pq_sendint64(StringInfo buf, uint64 i)
Definition: pqformat.h:152
char * c
StringInfoData * StringInfo
Definition: stringinfo.h:54
bool TransactionIdPrecedes(TransactionId id1, TransactionId id2)
Definition: transam.c:280
#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:606
#define PG_GETARG_FULLTRANSACTIONID(X)
Definition: xid8.h:29
#define PG_RETURN_FULLTRANSACTIONID(X)
Definition: xid8.h:30
#define PG_RETURN_COMMANDID(x)
Definition: xid.c:29
Datum xidneq(PG_FUNCTION_ARGS)
Definition: xid.c:93
Datum hashxid(PG_FUNCTION_ARGS)
Definition: xid.c:102
#define PG_GETARG_COMMANDID(n)
Definition: xid.c:28
int xidComparator(const void *arg1, const void *arg2)
Definition: xid.c:152
Datum xid8ge(PG_FUNCTION_ARGS)
Definition: xid.c:281
Datum cidin(PG_FUNCTION_ARGS)
Definition: xid.c:347
Datum xideq(PG_FUNCTION_ARGS)
Definition: xid.c:81
Datum hashcid(PG_FUNCTION_ARGS)
Definition: xid.c:404
Datum cidout(PG_FUNCTION_ARGS)
Definition: xid.c:360
Datum xid_age(PG_FUNCTION_ARGS)
Definition: xid.c:117
Datum xid8toxid(PG_FUNCTION_ARGS)
Definition: xid.c:187
Datum hashxid8(PG_FUNCTION_ARGS)
Definition: xid.c:304
Datum xidrecv(PG_FUNCTION_ARGS)
Definition: xid.c:56
Datum xid8_larger(PG_FUNCTION_ARGS)
Definition: xid.c:316
int xidLogicalComparator(const void *arg1, const void *arg2)
Definition: xid.c:169
Datum xid8eq(PG_FUNCTION_ARGS)
Definition: xid.c:236
Datum hashcidextended(PG_FUNCTION_ARGS)
Definition: xid.c:410
Datum xid8in(PG_FUNCTION_ARGS)
Definition: xid.c:195
Datum xid8_smaller(PG_FUNCTION_ARGS)
Definition: xid.c:328
Datum xid8cmp(PG_FUNCTION_ARGS)
Definition: xid.c:290
Datum cideq(PG_FUNCTION_ARGS)
Definition: xid.c:395
Datum xid8send(PG_FUNCTION_ARGS)
Definition: xid.c:225
Datum xid8gt(PG_FUNCTION_ARGS)
Definition: xid.c:263
Datum xidin(PG_FUNCTION_ARGS)
Definition: xid.c:33
Datum cidrecv(PG_FUNCTION_ARGS)
Definition: xid.c:373
Datum xid8lt(PG_FUNCTION_ARGS)
Definition: xid.c:254
Datum xidsend(PG_FUNCTION_ARGS)
Definition: xid.c:67
Datum xid8ne(PG_FUNCTION_ARGS)
Definition: xid.c:245
Datum xid8le(PG_FUNCTION_ARGS)
Definition: xid.c:272
Datum hashxidextended(PG_FUNCTION_ARGS)
Definition: xid.c:108
Datum xid8recv(PG_FUNCTION_ARGS)
Definition: xid.c:215
Datum mxid_age(PG_FUNCTION_ARGS)
Definition: xid.c:133
Datum cidsend(PG_FUNCTION_ARGS)
Definition: xid.c:384
Datum xid8out(PG_FUNCTION_ARGS)
Definition: xid.c:205
Datum hashxid8extended(PG_FUNCTION_ARGS)
Definition: xid.c:310
Datum xidout(PG_FUNCTION_ARGS)
Definition: xid.c:43