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 <[email protected]>
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