*
* xid.c
* openGauss transaction identifier and command identifier datatypes.
*
* Portions Copyright (c) 1996-2012, 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 "knl/knl_variable.h"
#include <limits.h>
#include "access/transam.h"
#include "access/xact.h"
#include "libpq/pqformat.h"
#include "utils/builtins.h"
#define PG_GETARG_COMMANDID(n) DatumGetCommandId(PG_GETARG_DATUM(n))
#define PG_RETURN_COMMANDID(x) return CommandIdGetDatum(x)
Datum xidin4(PG_FUNCTION_ARGS)
{
char* str = PG_GETARG_CSTRING(0);
PG_RETURN_SHORTTRANSACTIONID((ShortTransactionId)strtoul(str, NULL, 0));
}
Datum xidout4(PG_FUNCTION_ARGS)
{
ShortTransactionId transactionId = PG_GETARG_SHORTTRANSACTIONID(0);
const size_t buffer_len = 11;
char* str = (char*)palloc(buffer_len);
errno_t ss_rc = 0;
ss_rc = snprintf_s(str, buffer_len, buffer_len - 1, "%lu", (unsigned long)transactionId);
securec_check_ss(ss_rc, "\0", "\0");
PG_RETURN_CSTRING(str);
}
* xidrecv - converts external binary format to xid
*/
Datum xidrecv4(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo)PG_GETARG_POINTER(0);
PG_RETURN_SHORTTRANSACTIONID((ShortTransactionId)pq_getmsgint(buf, sizeof(ShortTransactionId)));
}
* xidsend - converts xid to binary format
*/
Datum xidsend4(PG_FUNCTION_ARGS)
{
ShortTransactionId arg1 = PG_GETARG_SHORTTRANSACTIONID(0);
StringInfoData buf;
pq_begintypsend(&buf);
pq_sendint32(&buf, arg1);
PG_RETURN_BYTEA_P(pq_endtypsend(&buf));
}
* xideq - are two xids equal?
*/
Datum xideq4(PG_FUNCTION_ARGS)
{
ShortTransactionId xid1 = PG_GETARG_SHORTTRANSACTIONID(0);
ShortTransactionId xid2 = PG_GETARG_SHORTTRANSACTIONID(1);
PG_RETURN_BOOL(TransactionIdEquals(xid1, xid2));
}
* xidlt - xid1 < xid2 ?
*/
Datum xidlt4(PG_FUNCTION_ARGS)
{
ShortTransactionId xid1 = PG_GETARG_SHORTTRANSACTIONID(0);
ShortTransactionId xid2 = PG_GETARG_SHORTTRANSACTIONID(1);
PG_RETURN_BOOL(TransactionIdPrecedes(xid1, xid2));
}
Datum xidin(PG_FUNCTION_ARGS)
{
char* str = PG_GETARG_CSTRING(0);
PG_RETURN_TRANSACTIONID((TransactionId)pg_strtouint64(str, NULL, 0));
}
Datum xidout(PG_FUNCTION_ARGS)
{
TransactionId transactionId = PG_GETARG_TRANSACTIONID(0);
const size_t buffer_len = 32;
char* str = (char*)palloc(buffer_len);
errno_t ss_rc = 0;
ss_rc = snprintf_s(str, buffer_len, buffer_len - 1, XID_FMT, transactionId);
securec_check_ss(ss_rc, "\0", "\0");
PG_RETURN_CSTRING(str);
}
* xidrecv - converts external binary format to xid
*/
Datum xidrecv(PG_FUNCTION_ARGS)
{
StringInfo buf = (StringInfo)PG_GETARG_POINTER(0);
uint32 lo, hi;
lo = (uint32)pq_getmsgint(buf, sizeof(TransactionId));
hi = (uint32)pq_getmsgint(buf, sizeof(TransactionId));
PG_RETURN_TRANSACTIONID((uint64)lo + ((uint64)hi << 32));
}
* xidsend - converts xid to binary format
*/
Datum xidsend(PG_FUNCTION_ARGS)
{
TransactionId arg1 = PG_GETARG_TRANSACTIONID(0);
StringInfoData buf;
uint32 lo, hi;
lo = (uint32)(arg1 & 0xFFFFFFFF);
hi = (uint32)(arg1 >> 32);
pq_begintypsend(&buf);
pq_sendint32(&buf, lo);
pq_sendint32(&buf, hi);
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));
}
* xidlt - xid1 < xid2 ?
*/
Datum xidlt(PG_FUNCTION_ARGS)
{
TransactionId xid1 = PG_GETARG_TRANSACTIONID(0);
TransactionId xid2 = PG_GETARG_TRANSACTIONID(1);
PG_RETURN_BOOL(TransactionIdPrecedes(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();
if (!TransactionIdIsNormal(xid))
PG_RETURN_TRANSACTIONID(UINT64_MAX);
PG_RETURN_TRANSACTIONID((TransactionId)(now - xid));
}
* xidComparator
* qsort comparison function for XIDs
*/
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;
}
int RemoveRepetitiveXids(TransactionId* xids, int nxid)
{
if (nxid <= 1)
return nxid;
qsort(xids, nxid, sizeof(TransactionId), xidComparator);
int i = 1;
while (i < nxid && xids[i] != xids[i - 1])
++i;
int cmp = i - 1;
++i;
for (; i < nxid; ++i) {
if (xids[i] == xids[cmp])
continue;
xids[++cmp] = xids[i];
}
Assert(cmp < nxid);
return cmp + 1;
}
* COMMAND IDENTIFIER ROUTINES *
*****************************************************************************/
* cidin - converts CommandId to internal representation.
*/
Datum cidin(PG_FUNCTION_ARGS)
{
char* s = PG_GETARG_CSTRING(0);
CommandId c;
c = atoi(s);
PG_RETURN_COMMANDID(c);
}
* cidout - converts a cid to external representation.
*/
Datum cidout(PG_FUNCTION_ARGS)
{
CommandId c = PG_GETARG_COMMANDID(0);
const size_t buffer_len = 16;
char* result = (char*)palloc(buffer_len);
errno_t ss_rc = 0;
ss_rc = snprintf_s(result, buffer_len, buffer_len - 1, "%u", (unsigned int)c);
securec_check_ss(ss_rc, "\0", "\0");
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);
}