From 8a4d038e354e98c1e5a5fd10ff8822a50ad1b4ae Mon Sep 17 00:00:00 2001
From: Craig Ringer <craig@2ndquadrant.com>
Date: Fri, 19 Aug 2016 14:46:53 +0800
Subject: [PATCH 2/4] Add txid_current_ifassigned()

Add a variant of txid_current() that returns null if no xid is assigned
instead of assigning one or, on a replica, ERRORing.

Per suggestion from Jim Nasby
---
 doc/src/sgml/func.sgml             |  9 +++++++++
 src/backend/utils/adt/txid.c       | 21 +++++++++++++++++++++
 src/include/catalog/pg_proc.h      |  2 ++
 src/test/regress/expected/txid.out | 15 +++++++++++++++
 src/test/regress/sql/txid.sql      |  6 ++++++
 5 files changed, 53 insertions(+)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 8edf490..9434e9b 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -17120,6 +17120,10 @@ SELECT collation for ('foo' COLLATE "de_DE");
    </indexterm>
 
    <indexterm>
+    <primary>txid_current_if_assigned</primary>
+   </indexterm>
+
+   <indexterm>
     <primary>txid_current_snapshot</primary>
    </indexterm>
 
@@ -17164,6 +17168,11 @@ SELECT collation for ('foo' COLLATE "de_DE");
        <entry>get current 64-bit transaction ID with epoch, assigning a new one if the current transaction does not have one</entry>
       </row>
       <row>
+       <entry><literal><function>txid_current_if_assigned()</function></literal></entry>
+       <entry><type>bigint</type></entry>
+       <entry>same as <function>txid_current()</function> but returns null instead of assigning an xid if none is already assigned</entry>
+      </row>
+      <row>
        <entry><literal><function>txid_current_snapshot()</function></literal></entry>
        <entry><type>txid_snapshot</type></entry>
        <entry>get current snapshot</entry>
diff --git a/src/backend/utils/adt/txid.c b/src/backend/utils/adt/txid.c
index 0480c99..05b0c96 100644
--- a/src/backend/utils/adt/txid.c
+++ b/src/backend/utils/adt/txid.c
@@ -426,6 +426,27 @@ txid_current(PG_FUNCTION_ARGS)
 }
 
 /*
+ * Same as txid_current() but doesn't assign a new xid if there isn't one
+ * yet.
+ */
+Datum
+txid_current_if_assigned(PG_FUNCTION_ARGS)
+{
+	txid		val;
+	TxidEpoch	state;
+	TransactionId	topxid = GetTopTransactionIdIfAny();
+
+	if (topxid == InvalidTransactionId)
+		PG_RETURN_NULL();
+
+	load_xid_epoch(&state);
+
+	val = convert_xid(topxid, &state);
+
+	PG_RETURN_INT64(val);
+}
+
+/*
  * txid_current_snapshot() returns txid_snapshot
  *
  *		Return current snapshot in TXID format
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index d99384c..80420ef 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -4904,6 +4904,8 @@ DATA(insert OID = 2942 (  txid_snapshot_send		PGNSP PGUID 12 1  0 0 0 f f f f t
 DESCR("I/O");
 DATA(insert OID = 2943 (  txid_current				PGNSP PGUID 12 1  0 0 0 f f f f t f s u 0 0 20 "" _null_ _null_ _null_ _null_ _null_ txid_current _null_ _null_ _null_ ));
 DESCR("get current transaction ID");
+DATA(insert OID = 3348 (  txid_current_if_assigned	PGNSP PGUID 12 1  0 0 0 f f f f t f s u 0 0 20 "" _null_ _null_ _null_ _null_ _null_ txid_current_if_assigned _null_ _null_ _null_ ));
+DESCR("get current transaction ID");
 DATA(insert OID = 2944 (  txid_current_snapshot		PGNSP PGUID 12 1  0 0 0 f f f f t f s s 0 0 2970 "" _null_ _null_ _null_ _null_ _null_ txid_current_snapshot _null_ _null_ _null_ ));
 DESCR("get current snapshot");
 DATA(insert OID = 2945 (  txid_snapshot_xmin		PGNSP PGUID 12 1  0 0 0 f f f f t f i s 1 0 20 "2970" _null_ _null_ _null_ _null_ _null_ txid_snapshot_xmin _null_ _null_ _null_ ));
diff --git a/src/test/regress/expected/txid.out b/src/test/regress/expected/txid.out
index 61299c5..9450d5e 100644
--- a/src/test/regress/expected/txid.out
+++ b/src/test/regress/expected/txid.out
@@ -238,6 +238,21 @@ SELECT txid_snapshot '1:9223372036854775808:3';
 ERROR:  invalid input syntax for type txid_snapshot: "1:9223372036854775808:3"
 LINE 1: SELECT txid_snapshot '1:9223372036854775808:3';
                              ^
+BEGIN;
+SELECT txid_current_if_assigned() IS NULL;
+ ?column? 
+----------
+ t
+(1 row)
+
+SELECT txid_current() \gset
+SELECT txid_current_if_assigned() IS NOT DISTINCT FROM BIGINT :'txid_current';
+ ?column? 
+----------
+ t
+(1 row)
+
+COMMIT;
 -- test xid status functions
 BEGIN;
 SELECT txid_current() AS committed \gset
diff --git a/src/test/regress/sql/txid.sql b/src/test/regress/sql/txid.sql
index 0bfdfe2..70e18e3 100644
--- a/src/test/regress/sql/txid.sql
+++ b/src/test/regress/sql/txid.sql
@@ -53,6 +53,12 @@ select txid_visible_in_snapshot('1000100010001015', '1000100010001000:1000100010
 SELECT txid_snapshot '1:9223372036854775807:3';
 SELECT txid_snapshot '1:9223372036854775808:3';
 
+BEGIN;
+SELECT txid_current_if_assigned() IS NULL;
+SELECT txid_current() \gset
+SELECT txid_current_if_assigned() IS NOT DISTINCT FROM BIGINT :'txid_current';
+COMMIT;
+
 -- test xid status functions
 BEGIN;
 SELECT txid_current() AS committed \gset
-- 
2.5.5

