Line data Source code
1 : /*-------------------------------------------------------------------------
2 : *
3 : * xid.c
4 : * POSTGRES transaction identifier and command identifier datatypes.
5 : *
6 : * Portions Copyright (c) 1996-2017, 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 :
25 : #define PG_GETARG_TRANSACTIONID(n) DatumGetTransactionId(PG_GETARG_DATUM(n))
26 : #define PG_RETURN_TRANSACTIONID(x) return TransactionIdGetDatum(x)
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
33 20 : xidin(PG_FUNCTION_ARGS)
34 : {
35 20 : char *str = PG_GETARG_CSTRING(0);
36 :
37 20 : PG_RETURN_TRANSACTIONID((TransactionId) strtoul(str, NULL, 0));
38 : }
39 :
40 : Datum
41 13 : xidout(PG_FUNCTION_ARGS)
42 : {
43 13 : TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
44 13 : char *result = (char *) palloc(16);
45 :
46 13 : snprintf(result, 16, "%lu", (unsigned long) transactionId);
47 13 : PG_RETURN_CSTRING(result);
48 : }
49 :
50 : /*
51 : * xidrecv - converts external binary format to xid
52 : */
53 : Datum
54 0 : xidrecv(PG_FUNCTION_ARGS)
55 : {
56 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
57 :
58 0 : PG_RETURN_TRANSACTIONID((TransactionId) pq_getmsgint(buf, sizeof(TransactionId)));
59 : }
60 :
61 : /*
62 : * xidsend - converts xid to binary format
63 : */
64 : Datum
65 0 : xidsend(PG_FUNCTION_ARGS)
66 : {
67 0 : TransactionId arg1 = PG_GETARG_TRANSACTIONID(0);
68 : StringInfoData buf;
69 :
70 0 : pq_begintypsend(&buf);
71 0 : pq_sendint(&buf, arg1, sizeof(arg1));
72 0 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
73 : }
74 :
75 : /*
76 : * xideq - are two xids equal?
77 : */
78 : Datum
79 12023 : xideq(PG_FUNCTION_ARGS)
80 : {
81 12023 : TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
82 12023 : TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
83 :
84 12023 : PG_RETURN_BOOL(TransactionIdEquals(xid1, xid2));
85 : }
86 :
87 : /*
88 : * xidneq - are two xids different?
89 : */
90 : Datum
91 0 : xidneq(PG_FUNCTION_ARGS)
92 : {
93 0 : TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
94 0 : TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
95 :
96 0 : PG_RETURN_BOOL(!TransactionIdEquals(xid1, xid2));
97 : }
98 :
99 : /*
100 : * xid_age - compute age of an XID (relative to latest stable xid)
101 : */
102 : Datum
103 0 : xid_age(PG_FUNCTION_ARGS)
104 : {
105 0 : TransactionId xid = PG_GETARG_TRANSACTIONID(0);
106 0 : TransactionId now = GetStableLatestTransactionId();
107 :
108 : /* Permanent XIDs are always infinitely old */
109 0 : if (!TransactionIdIsNormal(xid))
110 0 : PG_RETURN_INT32(INT_MAX);
111 :
112 0 : PG_RETURN_INT32((int32) (now - xid));
113 : }
114 :
115 : /*
116 : * mxid_age - compute age of a multi XID (relative to latest stable mxid)
117 : */
118 : Datum
119 0 : mxid_age(PG_FUNCTION_ARGS)
120 : {
121 0 : TransactionId xid = PG_GETARG_TRANSACTIONID(0);
122 0 : MultiXactId now = ReadNextMultiXactId();
123 :
124 0 : if (!MultiXactIdIsValid(xid))
125 0 : PG_RETURN_INT32(INT_MAX);
126 :
127 0 : PG_RETURN_INT32((int32) (now - xid));
128 : }
129 :
130 : /*
131 : * xidComparator
132 : * qsort comparison function for XIDs
133 : *
134 : * We can't use wraparound comparison for XIDs because that does not respect
135 : * the triangle inequality! Any old sort order will do.
136 : */
137 : int
138 7 : xidComparator(const void *arg1, const void *arg2)
139 : {
140 7 : TransactionId xid1 = *(const TransactionId *) arg1;
141 7 : TransactionId xid2 = *(const TransactionId *) arg2;
142 :
143 7 : if (xid1 > xid2)
144 7 : return 1;
145 0 : if (xid1 < xid2)
146 0 : return -1;
147 0 : return 0;
148 : }
149 :
150 : /*****************************************************************************
151 : * COMMAND IDENTIFIER ROUTINES *
152 : *****************************************************************************/
153 :
154 : /*
155 : * cidin - converts CommandId to internal representation.
156 : */
157 : Datum
158 0 : cidin(PG_FUNCTION_ARGS)
159 : {
160 0 : char *str = PG_GETARG_CSTRING(0);
161 :
162 0 : PG_RETURN_COMMANDID((CommandId) strtoul(str, NULL, 0));
163 : }
164 :
165 : /*
166 : * cidout - converts a cid to external representation.
167 : */
168 : Datum
169 31 : cidout(PG_FUNCTION_ARGS)
170 : {
171 31 : CommandId c = PG_GETARG_COMMANDID(0);
172 31 : char *result = (char *) palloc(16);
173 :
174 31 : snprintf(result, 16, "%lu", (unsigned long) c);
175 31 : PG_RETURN_CSTRING(result);
176 : }
177 :
178 : /*
179 : * cidrecv - converts external binary format to cid
180 : */
181 : Datum
182 0 : cidrecv(PG_FUNCTION_ARGS)
183 : {
184 0 : StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
185 :
186 0 : PG_RETURN_COMMANDID((CommandId) pq_getmsgint(buf, sizeof(CommandId)));
187 : }
188 :
189 : /*
190 : * cidsend - converts cid to binary format
191 : */
192 : Datum
193 0 : cidsend(PG_FUNCTION_ARGS)
194 : {
195 0 : CommandId arg1 = PG_GETARG_COMMANDID(0);
196 : StringInfoData buf;
197 :
198 0 : pq_begintypsend(&buf);
199 0 : pq_sendint(&buf, arg1, sizeof(arg1));
200 0 : PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
201 : }
202 :
203 : Datum
204 0 : cideq(PG_FUNCTION_ARGS)
205 : {
206 0 : CommandId arg1 = PG_GETARG_COMMANDID(0);
207 0 : CommandId arg2 = PG_GETARG_COMMANDID(1);
208 :
209 0 : PG_RETURN_BOOL(arg1 == arg2);
210 : }
|