Hi all

During the committs / replorigin split, the function to query the
replication origin of a transaction from user space was lost.

A function to do so is utterly trivial, e.g.

Datum
pg_get_xact_replication_origin(PG_FUNCTION_ARGS)
{
    TransactionId xid = PG_GETARG_TRANSACTIONID(0);
    TimestampTz ts;
    RepOriginId nodeid;

    if (TransactionIdGetCommitTsData(xid, &ts, &nodeid))
        PG_RETURN_INT32((int32)nodeid);
    else
        PG_RETURN_NULL();
}

... but it probably makes more sense to extend pg_xact_commit_timestamp
with support for returning the origin too.

pg_xact_commit_timestamp() is a scalar function so I don't want to extend
it directly because that'll upset existing callers.

pg_xact_commit_timestamp_origin()

(unsure if a "with" or "and" is appropriate or too long).

Attached. Also add 'roident' to pg_last_committed_xact() to make the info
available there too. It was already record-returning so I'm not overly
concerned about adding a column.

-- 
 Craig Ringer                   http://www.2ndQuadrant.com/
 PostgreSQL Development, 24x7 Support, Training & Services
From e022ad7168936800fb18f397e7f42538871e27d3 Mon Sep 17 00:00:00 2001
From: Craig Ringer <cr...@2ndquadrant.com>
Date: Mon, 26 Mar 2018 16:23:59 +0800
Subject: [PATCH v1] Add pg_xact_commit_timestamp_origin()

Add an extended version of pg_xact_commit_timestamp(), called
pg_xact_commit_timestamp_origin(), that returns the replication origin
as well as the commit timestamp.

It's done this way rather than as a wholly separate function because
replication origin information is tracked alongside commit timestamps,
and it's significantly more efficient to fetch both at once.

Also extend pg_last_committed_xact() with a roident column with
the replication origin of the last committed transaction.
---
 doc/src/sgml/func.sgml                             | 17 +++++--
 src/backend/access/transam/commit_ts.c             | 59 +++++++++++++++++++---
 src/include/catalog/pg_proc.h                      |  5 +-
 src/test/modules/commit_ts/commit_ts.conf          |  2 +-
 .../commit_ts/expected/commit_timestamp.out        | 49 ++++++++++++++++--
 .../commit_ts/expected/commit_timestamp_1.out      | 34 ++++++++++++-
 .../modules/commit_ts/sql/commit_timestamp.sql     | 14 ++++-
 7 files changed, 162 insertions(+), 18 deletions(-)

diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 7b1a85fc71..dae5fef6c8 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -17928,7 +17928,9 @@ SELECT collation for ('foo' COLLATE "de_DE");
     These functions mainly provide information about when the transactions
     were committed. They only provide useful data when
     <xref linkend="guc-track-commit-timestamp"/> configuration option is enabled
-    and only for transactions that were committed after it was enabled.
+    and only for transactions that were committed after it was enabled. The reported
+    replication origin information is maintained by the <link linkend="replication-origins">
+    replication origins</link> subsystem.
    </para>
 
    <table id="functions-commit-timestamp">
@@ -17948,13 +17950,22 @@ SELECT collation for ('foo' COLLATE "de_DE");
        <entry>get commit timestamp of a transaction</entry>
       </row>
 
+      <row>
+       <entry>
+        <indexterm><primary>pg_xact_commit_timestamp_origin</primary></indexterm>
+        <literal><function>pg_xact_commit_timestamp_origin(<parameter>xid</parameter>)</function></literal>
+       </entry>
+       <entry><parameter>timestamp</parameter> <type>timestamptz</type>, <parameter>roident</parameter> <type>oid</type></entry>
+       <entry>get commit timestamp and replication origin of a transaction</entry>
+      </row>
+
       <row>
        <entry>
         <indexterm><primary>pg_last_committed_xact</primary></indexterm>
         <literal><function>pg_last_committed_xact()</function></literal>
        </entry>
-       <entry><parameter>xid</parameter> <type>xid</type>, <parameter>timestamp</parameter> <type>timestamp with time zone</type></entry>
-       <entry>get transaction ID and commit timestamp of latest committed transaction</entry>
+       <entry><parameter>xid</parameter> <type>xid</type>, <parameter>timestamp</parameter> <type>timestamp with time zone</type>, <parameter>roident</parameter> <type>oid</type></entry>
+       <entry>get transaction ID, commit timestamp and replication origin of latest committed transaction</entry>
       </row>
      </tbody>
     </tgroup>
diff --git a/src/backend/access/transam/commit_ts.c b/src/backend/access/transam/commit_ts.c
index 04a15e4e29..73d4ac0a9c 100644
--- a/src/backend/access/transam/commit_ts.c
+++ b/src/backend/access/transam/commit_ts.c
@@ -416,29 +416,73 @@ pg_xact_commit_timestamp(PG_FUNCTION_ARGS)
 	PG_RETURN_TIMESTAMPTZ(ts);
 }
 
-
 Datum
-pg_last_committed_xact(PG_FUNCTION_ARGS)
+pg_xact_commit_timestamp_origin(PG_FUNCTION_ARGS)
 {
-	TransactionId xid;
+	TransactionId xid = PG_GETARG_UINT32(0);
 	TimestampTz ts;
+	RepOriginId	origin;
+	bool		found;
+	TupleDesc	tupdesc;
 	Datum		values[2];
-	bool		nulls[2];
+	bool		nulls[2] = {false, false};
+	HeapTuple	tup;
+
+	/*
+	 * Construct a tuple descriptor for the result row.  This must match this
+	 * function's pg_proc entry!
+	 */
+	tupdesc = CreateTemplateTupleDesc(2, false);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "timestamp",
+					   TIMESTAMPTZOID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "roident",
+					   OIDOID, -1, 0);
+	tupdesc = BlessTupleDesc(tupdesc);
+
+	found = TransactionIdGetCommitTsData(xid, &ts, &origin);
+
+	if (found)
+	{
+		values[0] = TimestampTzGetDatum(ts);
+		values[1] = ObjectIdGetDatum(origin);
+	}
+	else
+	{
+		values[0] = (Datum)0;
+		nulls[0] = true;
+		values[1] = (Datum)0;
+		nulls[1] = true;
+	}
+
+	tup = heap_form_tuple(tupdesc, values, nulls);
+	PG_RETURN_DATUM(HeapTupleGetDatum(tup));
+}
+
+Datum
+pg_last_committed_xact(PG_FUNCTION_ARGS)
+{
+	TransactionId xid;
+	TimestampTz ts;
+	Datum		values[3];
+	bool		nulls[3];
 	TupleDesc	tupdesc;
 	HeapTuple	htup;
+	RepOriginId	origin;
 
 	/* and construct a tuple with our data */
-	xid = GetLatestCommitTsData(&ts, NULL);
+	xid = GetLatestCommitTsData(&ts, &origin);
 
 	/*
 	 * Construct a tuple descriptor for the result row.  This must match this
 	 * function's pg_proc entry!
 	 */
-	tupdesc = CreateTemplateTupleDesc(2, false);
+	tupdesc = CreateTemplateTupleDesc(3, false);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 1, "xid",
 					   XIDOID, -1, 0);
 	TupleDescInitEntry(tupdesc, (AttrNumber) 2, "timestamp",
 					   TIMESTAMPTZOID, -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 3, "roident",
+					   OIDOID, -1, 0);
 	tupdesc = BlessTupleDesc(tupdesc);
 
 	if (!TransactionIdIsNormal(xid))
@@ -452,6 +496,9 @@ pg_last_committed_xact(PG_FUNCTION_ARGS)
 
 		values[1] = TimestampTzGetDatum(ts);
 		nulls[1] = false;
+
+		values[2] = ObjectIdGetDatum(origin);
+		nulls[2] = false;
 	}
 
 	htup = heap_form_tuple(tupdesc, values, nulls);
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index bfc90098f8..b6220efa75 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3237,7 +3237,10 @@ DESCR("view members of a multixactid");
 DATA(insert OID = 3581 ( pg_xact_commit_timestamp PGNSP PGUID 12 1 0 0 0 f f f t f v s 1 0 1184 "28" _null_ _null_ _null_ _null_ _null_ pg_xact_commit_timestamp _null_ _null_ _null_ ));
 DESCR("get commit timestamp of a transaction");
 
-DATA(insert OID = 3583 ( pg_last_committed_xact PGNSP PGUID 12 1 0 0 0 f f f t f v s 0 0 2249 "" "{28,1184}" "{o,o}" "{xid,timestamp}" _null_ _null_ pg_last_committed_xact _null_ _null_ _null_ ));
+DATA(insert OID = 3423 ( pg_xact_commit_timestamp_origin PGNSP PGUID 12 1 0 0 0 f f f t f v s 1 0 2249 "28" "{28,1184,26}" "{i,o,o}" "{xid,timestamp,roident}" _null_ _null_ pg_xact_commit_timestamp_origin _null_ _null_ _null_ ));
+DESCR("get commit timestamp and replication origin of a transaction");
+
+DATA(insert OID = 3583 ( pg_last_committed_xact PGNSP PGUID 12 1 0 0 0 f f f t f v s 0 0 2249 "" "{28,1184,26}" "{o,o,o}" "{xid,timestamp,roident}" _null_ _null_ pg_last_committed_xact _null_ _null_ _null_ ));
 DESCR("get transaction Id and commit timestamp of latest transaction commit");
 
 DATA(insert OID = 3537 (  pg_describe_object		PGNSP PGUID 12 1 0 0 0 f f f t f s s 3 0 25 "26 26 23" _null_ _null_ _null_ _null_ _null_ pg_describe_object _null_ _null_ _null_ ));
diff --git a/src/test/modules/commit_ts/commit_ts.conf b/src/test/modules/commit_ts/commit_ts.conf
index e9d3c35756..ddd13213ad 100644
--- a/src/test/modules/commit_ts/commit_ts.conf
+++ b/src/test/modules/commit_ts/commit_ts.conf
@@ -1 +1 @@
-track_commit_timestamp = on
+track_commit_timestamp = off
diff --git a/src/test/modules/commit_ts/expected/commit_timestamp.out b/src/test/modules/commit_ts/expected/commit_timestamp.out
index 5b7783b58f..048b1af7da 100644
--- a/src/test/modules/commit_ts/expected/commit_timestamp.out
+++ b/src/test/modules/commit_ts/expected/commit_timestamp.out
@@ -11,6 +11,33 @@ CREATE TABLE committs_test(id serial, ts timestamptz default now());
 INSERT INTO committs_test DEFAULT VALUES;
 INSERT INTO committs_test DEFAULT VALUES;
 INSERT INTO committs_test DEFAULT VALUES;
+SELECT pg_replication_origin_create('test_origin');
+ pg_replication_origin_create 
+------------------------------
+                            1
+(1 row)
+
+SELECT pg_replication_origin_session_setup('test_origin');
+ pg_replication_origin_session_setup 
+-------------------------------------
+ 
+(1 row)
+
+BEGIN;
+SELECT pg_replication_origin_xact_setup('1/1', '1990-01-01');
+ pg_replication_origin_xact_setup 
+----------------------------------
+ 
+(1 row)
+
+INSERT INTO committs_test DEFAULT VALUES;
+COMMIT;
+SELECT pg_replication_origin_session_reset();
+ pg_replication_origin_session_reset 
+-------------------------------------
+ 
+(1 row)
+
 SELECT id,
        pg_xact_commit_timestamp(xmin) >= ts,
        pg_xact_commit_timestamp(xmin) <= now(),
@@ -22,7 +49,19 @@ ORDER BY id;
   1 | t        | t        | t
   2 | t        | t        | t
   3 | t        | t        | t
-(3 rows)
+  4 | f        | t        | t
+(4 rows)
+
+SELECT roident = 0, roident = 1
+FROM committs_test, pg_xact_commit_timestamp_origin(xmin)
+ORDER BY id;
+ ?column? | ?column? 
+----------+----------
+ t        | f
+ t        | f
+ t        | f
+ f        | t
+(4 rows)
 
 DROP TABLE committs_test;
 SELECT pg_xact_commit_timestamp('0'::xid);
@@ -39,9 +78,9 @@ SELECT pg_xact_commit_timestamp('2'::xid);
  
 (1 row)
 
-SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now() FROM pg_last_committed_xact() x;
- ?column? | ?column? | ?column? 
-----------+----------+----------
- t        | t        | t
+SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now(), roident = 0 FROM pg_last_committed_xact() x;
+ ?column? | ?column? | ?column? | ?column? 
+----------+----------+----------+----------
+ t        | t        | t        | t
 (1 row)
 
diff --git a/src/test/modules/commit_ts/expected/commit_timestamp_1.out b/src/test/modules/commit_ts/expected/commit_timestamp_1.out
index c10b0abc2b..2546a46441 100644
--- a/src/test/modules/commit_ts/expected/commit_timestamp_1.out
+++ b/src/test/modules/commit_ts/expected/commit_timestamp_1.out
@@ -11,6 +11,33 @@ CREATE TABLE committs_test(id serial, ts timestamptz default now());
 INSERT INTO committs_test DEFAULT VALUES;
 INSERT INTO committs_test DEFAULT VALUES;
 INSERT INTO committs_test DEFAULT VALUES;
+SELECT pg_replication_origin_create('test_origin');
+ pg_replication_origin_create 
+------------------------------
+                            1
+(1 row)
+
+SELECT pg_replication_origin_session_setup('test_origin');
+ pg_replication_origin_session_setup 
+-------------------------------------
+ 
+(1 row)
+
+BEGIN;
+SELECT pg_replication_origin_xact_setup('1/1', '1990-01-01');
+ pg_replication_origin_xact_setup 
+----------------------------------
+ 
+(1 row)
+
+INSERT INTO committs_test DEFAULT VALUES;
+COMMIT;
+SELECT pg_replication_origin_session_reset();
+ pg_replication_origin_session_reset 
+-------------------------------------
+ 
+(1 row)
+
 SELECT id,
        pg_xact_commit_timestamp(xmin) >= ts,
        pg_xact_commit_timestamp(xmin) <= now(),
@@ -19,6 +46,11 @@ FROM committs_test
 ORDER BY id;
 ERROR:  could not get commit timestamp data
 HINT:  Make sure the configuration parameter "track_commit_timestamp" is set.
+SELECT roident = 0, roident = 1
+FROM committs_test, pg_xact_commit_timestamp_origin(xmin)
+ORDER BY id;
+ERROR:  could not get commit timestamp data
+HINT:  Make sure the configuration parameter "track_commit_timestamp" is set.
 DROP TABLE committs_test;
 SELECT pg_xact_commit_timestamp('0'::xid);
 ERROR:  cannot retrieve commit timestamp for transaction 0
@@ -34,6 +66,6 @@ SELECT pg_xact_commit_timestamp('2'::xid);
  
 (1 row)
 
-SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now() FROM pg_last_committed_xact() x;
+SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now(), roident = 0 FROM pg_last_committed_xact() x;
 ERROR:  could not get commit timestamp data
 HINT:  Make sure the configuration parameter "track_commit_timestamp" is set.
diff --git a/src/test/modules/commit_ts/sql/commit_timestamp.sql b/src/test/modules/commit_ts/sql/commit_timestamp.sql
index 4e041a5347..896f7ea6bd 100644
--- a/src/test/modules/commit_ts/sql/commit_timestamp.sql
+++ b/src/test/modules/commit_ts/sql/commit_timestamp.sql
@@ -8,6 +8,14 @@ INSERT INTO committs_test DEFAULT VALUES;
 INSERT INTO committs_test DEFAULT VALUES;
 INSERT INTO committs_test DEFAULT VALUES;
 
+SELECT pg_replication_origin_create('test_origin');
+SELECT pg_replication_origin_session_setup('test_origin');
+BEGIN;
+SELECT pg_replication_origin_xact_setup('1/1', '1990-01-01');
+INSERT INTO committs_test DEFAULT VALUES;
+COMMIT;
+SELECT pg_replication_origin_session_reset();
+
 SELECT id,
        pg_xact_commit_timestamp(xmin) >= ts,
        pg_xact_commit_timestamp(xmin) <= now(),
@@ -15,10 +23,14 @@ SELECT id,
 FROM committs_test
 ORDER BY id;
 
+SELECT roident = 0, roident = 1
+FROM committs_test, pg_xact_commit_timestamp_origin(xmin)
+ORDER BY id;
+
 DROP TABLE committs_test;
 
 SELECT pg_xact_commit_timestamp('0'::xid);
 SELECT pg_xact_commit_timestamp('1'::xid);
 SELECT pg_xact_commit_timestamp('2'::xid);
 
-SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now() FROM pg_last_committed_xact() x;
+SELECT x.xid::text::bigint > 0, x.timestamp > '-infinity'::timestamptz, x.timestamp <= now(), roident = 0 FROM pg_last_committed_xact() x;
-- 
2.14.3

Reply via email to