summaryrefslogtreecommitdiffstats
path: root/src/backend/utils/adt/xid.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/backend/utils/adt/xid.c349
1 files changed, 349 insertions, 0 deletions
diff --git a/src/backend/utils/adt/xid.c b/src/backend/utils/adt/xid.c
new file mode 100644
index 0000000..faa7737
--- /dev/null
+++ b/src/backend/utils/adt/xid.c
@@ -0,0 +1,349 @@
+/*-------------------------------------------------------------------------
+ *
+ * xid.c
+ * POSTGRES transaction identifier and command identifier datatypes.
+ *
+ * Portions Copyright (c) 1996-2021, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ * src/backend/utils/adt/xid.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include <limits.h>
+
+#include "access/multixact.h"
+#include "access/transam.h"
+#include "access/xact.h"
+#include "libpq/pqformat.h"
+#include "utils/builtins.h"
+#include "utils/xid8.h"
+
+#define PG_GETARG_COMMANDID(n) DatumGetCommandId(PG_GETARG_DATUM(n))
+#define PG_RETURN_COMMANDID(x) return CommandIdGetDatum(x)
+
+
+Datum
+xidin(PG_FUNCTION_ARGS)
+{
+ char *str = PG_GETARG_CSTRING(0);
+
+ PG_RETURN_TRANSACTIONID((TransactionId) strtoul(str, NULL, 0));
+}
+
+Datum
+xidout(PG_FUNCTION_ARGS)
+{
+ TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
+ char *result = (char *) palloc(16);
+
+ snprintf(result, 16, "%lu", (unsigned long) transactionId);
+ PG_RETURN_CSTRING(result);
+}
+
+/*
+ * xidrecv - converts external binary format to xid
+ */
+Datum
+xidrecv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+
+ PG_RETURN_TRANSACTIONID((TransactionId) pq_getmsgint(buf, sizeof(TransactionId)));
+}
+
+/*
+ * xidsend - converts xid to binary format
+ */
+Datum
+xidsend(PG_FUNCTION_ARGS)
+{
+ TransactionId arg1 = PG_GETARG_TRANSACTIONID(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendint32(&buf, arg1);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+/*
+ * xideq - are two xids equal?
+ */
+Datum
+xideq(PG_FUNCTION_ARGS)
+{
+ TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
+ TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
+
+ PG_RETURN_BOOL(TransactionIdEquals(xid1, xid2));
+}
+
+/*
+ * xidneq - are two xids different?
+ */
+Datum
+xidneq(PG_FUNCTION_ARGS)
+{
+ TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
+ TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
+
+ PG_RETURN_BOOL(!TransactionIdEquals(xid1, xid2));
+}
+
+/*
+ * xid_age - compute age of an XID (relative to latest stable xid)
+ */
+Datum
+xid_age(PG_FUNCTION_ARGS)
+{
+ TransactionId xid = PG_GETARG_TRANSACTIONID(0);
+ TransactionId now = GetStableLatestTransactionId();
+
+ /* Permanent XIDs are always infinitely old */
+ if (!TransactionIdIsNormal(xid))
+ PG_RETURN_INT32(INT_MAX);
+
+ PG_RETURN_INT32((int32) (now - xid));
+}
+
+/*
+ * mxid_age - compute age of a multi XID (relative to latest stable mxid)
+ */
+Datum
+mxid_age(PG_FUNCTION_ARGS)
+{
+ TransactionId xid = PG_GETARG_TRANSACTIONID(0);
+ MultiXactId now = ReadNextMultiXactId();
+
+ if (!MultiXactIdIsValid(xid))
+ PG_RETURN_INT32(INT_MAX);
+
+ PG_RETURN_INT32((int32) (now - xid));
+}
+
+/*
+ * xidComparator
+ * qsort comparison function for XIDs
+ *
+ * We can't use wraparound comparison for XIDs because that does not respect
+ * the triangle inequality! Any old sort order will do.
+ */
+int
+xidComparator(const void *arg1, const void *arg2)
+{
+ TransactionId xid1 = *(const TransactionId *) arg1;
+ TransactionId xid2 = *(const TransactionId *) arg2;
+
+ if (xid1 > xid2)
+ return 1;
+ if (xid1 < xid2)
+ return -1;
+ return 0;
+}
+
+/*
+ * xidLogicalComparator
+ * qsort comparison function for XIDs
+ *
+ * This is used to compare only XIDs from the same epoch (e.g. for backends
+ * running at the same time). So there must be only normal XIDs, so there's
+ * no issue with triangle inequality.
+ */
+int
+xidLogicalComparator(const void *arg1, const void *arg2)
+{
+ TransactionId xid1 = *(const TransactionId *) arg1;
+ TransactionId xid2 = *(const TransactionId *) arg2;
+
+ Assert(TransactionIdIsNormal(xid1));
+ Assert(TransactionIdIsNormal(xid2));
+
+ if (TransactionIdPrecedes(xid1, xid2))
+ return -1;
+
+ if (TransactionIdPrecedes(xid2, xid1))
+ return 1;
+
+ return 0;
+}
+
+Datum
+xid8toxid(PG_FUNCTION_ARGS)
+{
+ FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
+
+ PG_RETURN_TRANSACTIONID(XidFromFullTransactionId(fxid));
+}
+
+Datum
+xid8in(PG_FUNCTION_ARGS)
+{
+ char *str = PG_GETARG_CSTRING(0);
+
+ PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(pg_strtouint64(str, NULL, 0)));
+}
+
+Datum
+xid8out(PG_FUNCTION_ARGS)
+{
+ FullTransactionId fxid = PG_GETARG_FULLTRANSACTIONID(0);
+ char *result = (char *) palloc(21);
+
+ snprintf(result, 21, UINT64_FORMAT, U64FromFullTransactionId(fxid));
+ PG_RETURN_CSTRING(result);
+}
+
+Datum
+xid8recv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+ uint64 value;
+
+ value = (uint64) pq_getmsgint64(buf);
+ PG_RETURN_FULLTRANSACTIONID(FullTransactionIdFromU64(value));
+}
+
+Datum
+xid8send(PG_FUNCTION_ARGS)
+{
+ FullTransactionId arg1 = PG_GETARG_FULLTRANSACTIONID(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendint64(&buf, (uint64) U64FromFullTransactionId(arg1));
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+Datum
+xid8eq(PG_FUNCTION_ARGS)
+{
+ FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
+ FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
+
+ PG_RETURN_BOOL(FullTransactionIdEquals(fxid1, fxid2));
+}
+
+Datum
+xid8ne(PG_FUNCTION_ARGS)
+{
+ FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
+ FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
+
+ PG_RETURN_BOOL(!FullTransactionIdEquals(fxid1, fxid2));
+}
+
+Datum
+xid8lt(PG_FUNCTION_ARGS)
+{
+ FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
+ FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
+
+ PG_RETURN_BOOL(FullTransactionIdPrecedes(fxid1, fxid2));
+}
+
+Datum
+xid8gt(PG_FUNCTION_ARGS)
+{
+ FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
+ FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
+
+ PG_RETURN_BOOL(FullTransactionIdFollows(fxid1, fxid2));
+}
+
+Datum
+xid8le(PG_FUNCTION_ARGS)
+{
+ FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
+ FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
+
+ PG_RETURN_BOOL(FullTransactionIdPrecedesOrEquals(fxid1, fxid2));
+}
+
+Datum
+xid8ge(PG_FUNCTION_ARGS)
+{
+ FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
+ FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
+
+ PG_RETURN_BOOL(FullTransactionIdFollowsOrEquals(fxid1, fxid2));
+}
+
+Datum
+xid8cmp(PG_FUNCTION_ARGS)
+{
+ FullTransactionId fxid1 = PG_GETARG_FULLTRANSACTIONID(0);
+ FullTransactionId fxid2 = PG_GETARG_FULLTRANSACTIONID(1);
+
+ if (FullTransactionIdFollows(fxid1, fxid2))
+ PG_RETURN_INT32(1);
+ else if (FullTransactionIdEquals(fxid1, fxid2))
+ PG_RETURN_INT32(0);
+ else
+ PG_RETURN_INT32(-1);
+}
+
+/*****************************************************************************
+ * COMMAND IDENTIFIER ROUTINES *
+ *****************************************************************************/
+
+/*
+ * cidin - converts CommandId to internal representation.
+ */
+Datum
+cidin(PG_FUNCTION_ARGS)
+{
+ char *str = PG_GETARG_CSTRING(0);
+
+ PG_RETURN_COMMANDID((CommandId) strtoul(str, NULL, 0));
+}
+
+/*
+ * cidout - converts a cid to external representation.
+ */
+Datum
+cidout(PG_FUNCTION_ARGS)
+{
+ CommandId c = PG_GETARG_COMMANDID(0);
+ char *result = (char *) palloc(16);
+
+ snprintf(result, 16, "%lu", (unsigned long) c);
+ PG_RETURN_CSTRING(result);
+}
+
+/*
+ * cidrecv - converts external binary format to cid
+ */
+Datum
+cidrecv(PG_FUNCTION_ARGS)
+{
+ StringInfo buf = (StringInfo) PG_GETARG_POINTER(0);
+
+ PG_RETURN_COMMANDID((CommandId) pq_getmsgint(buf, sizeof(CommandId)));
+}
+
+/*
+ * cidsend - converts cid to binary format
+ */
+Datum
+cidsend(PG_FUNCTION_ARGS)
+{
+ CommandId arg1 = PG_GETARG_COMMANDID(0);
+ StringInfoData buf;
+
+ pq_begintypsend(&buf);
+ pq_sendint32(&buf, arg1);
+ PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
+}
+
+Datum
+cideq(PG_FUNCTION_ARGS)
+{
+ CommandId arg1 = PG_GETARG_COMMANDID(0);
+ CommandId arg2 = PG_GETARG_COMMANDID(1);
+
+ PG_RETURN_BOOL(arg1 == arg2);
+}