/******************************************************************************
  Functions to get information about transaction status.
  Written by Christian A. Plattner, plattner{insert at}inf.ethz.ch
  Last change: 19.06.2003

  'uint32 ejdbc_get_xid()' returns the current xid

  'text ejedbc_test_xid(uint32)' returns the status of the given xid
  Possible outcomes:
  "INVALID" : This xid has not been used up to now
  "COMMITED" : This xid was committed
  "ABORTED" : This xid was aborted
  "INPROGRESS" : This xid was not commited nor aborted
    (in case of read-only xid's, this will be also the final state).

*****************************************************************************/

#include "postgres.h"

#include "fmgr.h"	
#include "access/xact.h"
#include "access/transam.h"

/* These prototypes just prevent possible warnings from gcc. */

Datum		ejdbc_get_xid(PG_FUNCTION_ARGS);
Datum		ejdbc_test_xid(PG_FUNCTION_ARGS);

PG_FUNCTION_INFO_V1(ejdbc_get_xid);

Datum
ejdbc_get_xid(PG_FUNCTION_ARGS)
{
	TransactionId my_xid = GetCurrentTransactionId();

	PG_RETURN_UINT32(my_xid);
}

PG_FUNCTION_INFO_V1(ejdbc_test_xid);

Datum
ejdbc_test_xid(PG_FUNCTION_ARGS)
{
	text *t = (text *) NULL;
	char *answer = (char*) NULL;

	TransactionId xid = PG_GETARG_UINT32(0);
	TransactionId next_xid = ReadNewTransactionId();

	/*
      we could make the following faster by calling 'TransactionIdGetStatus' directly
      but that would ignore the usage comment in the TransactionIdGetStatus function
   */

	if (! TransactionIdPrecedes(xid, next_xid))
	{
		answer = "INVALID";
	}
	else if (TransactionIdDidCommit(xid))
	{
		answer = "COMMITTED";
	}
	else if (TransactionIdDidAbort(xid))
	{
		answer = "ABORTED";
	}
	else // lets ignore 0x03 and treat it as 0x00 (INPROGRESS)
	{
		answer = "INPROGRESS";
	}

	t = (text *) palloc(VARHDRSZ + strlen(answer));
	VARATT_SIZEP(t) = VARHDRSZ + strlen(answer);
	memcpy((void *) VARDATA(t), answer, strlen(answer));

	PG_RETURN_TEXT_P(t);
}

