summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2022-07-04 14:52:12 +0200
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2022-07-04 14:52:12 +0200
commitf10a025cfe97c1a341f636368e67af5ca644c5d8 (patch)
tree54e24a8088feaec1b65fba755a7329f18a5f0687
parent55f4802785f66a584c05dca40e5d9b25491674b2 (diff)
downloadpostgresql-f10a025cfe97c1a341f636368e67af5ca644c5d8.tar.gz
Implement List support for TransactionId
Use it for RelationSyncEntry->streamed_txns, which is currently using an integer list. The API support is not complete, not because it is hard to write but because it's unclear that it's worth the code space, there being so little use of XID lists. Discussion: https://postgr.es/m/202205130830.g5ntonhztspb@alvherre.pgsql Reviewed-by: Amit Kapila <amit.kapila16@gmail.com>
-rw-r--r--src/backend/nodes/list.c42
-rw-r--r--src/backend/nodes/outfuncs.c4
-rw-r--r--src/backend/replication/pgoutput/pgoutput.c14
-rw-r--r--src/include/nodes/nodes.h1
-rw-r--r--src/include/nodes/pg_list.h21
5 files changed, 70 insertions, 12 deletions
diff --git a/src/backend/nodes/list.c b/src/backend/nodes/list.c
index f843f861ef..9d8f4fd5c7 100644
--- a/src/backend/nodes/list.c
+++ b/src/backend/nodes/list.c
@@ -54,6 +54,7 @@
#define IsPointerList(l) ((l) == NIL || IsA((l), List))
#define IsIntegerList(l) ((l) == NIL || IsA((l), IntList))
#define IsOidList(l) ((l) == NIL || IsA((l), OidList))
+#define IsXidList(l) ((l) == NIL || IsA((l), XidList))
#ifdef USE_ASSERT_CHECKING
/*
@@ -71,7 +72,8 @@ check_list_invariants(const List *list)
Assert(list->type == T_List ||
list->type == T_IntList ||
- list->type == T_OidList);
+ list->type == T_OidList ||
+ list->type == T_XidList);
}
#else
#define check_list_invariants(l) ((void) 0)
@@ -384,6 +386,24 @@ lappend_oid(List *list, Oid datum)
}
/*
+ * Append a TransactionId to the specified list. See lappend()
+ */
+List *
+lappend_xid(List *list, TransactionId datum)
+{
+ Assert(IsXidList(list));
+
+ if (list == NIL)
+ list = new_list(T_XidList, 1);
+ else
+ new_tail_cell(list);
+
+ llast_xid(list) = datum;
+ check_list_invariants(list);
+ return list;
+}
+
+/*
* Make room for a new cell at position 'pos' (measured from 0).
* The data in the cell is left undefined, and must be filled in by the
* caller. 'list' is assumed to be non-NIL, and 'pos' must be a valid
@@ -715,6 +735,26 @@ list_member_oid(const List *list, Oid datum)
}
/*
+ * Return true iff the TransactionId 'datum' is a member of the list.
+ */
+bool
+list_member_xid(const List *list, TransactionId datum)
+{
+ const ListCell *cell;
+
+ Assert(IsXidList(list));
+ check_list_invariants(list);
+
+ foreach(cell, list)
+ {
+ if (lfirst_oid(cell) == datum)
+ return true;
+ }
+
+ return false;
+}
+
+/*
* Delete the n'th cell (counting from 0) in list.
*
* The List is pfree'd if this was the last member.
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index ce12915592..4315c53080 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -221,6 +221,8 @@ _outList(StringInfo str, const List *node)
appendStringInfoChar(str, 'i');
else if (IsA(node, OidList))
appendStringInfoChar(str, 'o');
+ else if (IsA(node, XidList))
+ appendStringInfoChar(str, 'x');
foreach(lc, node)
{
@@ -239,6 +241,8 @@ _outList(StringInfo str, const List *node)
appendStringInfo(str, " %d", lfirst_int(lc));
else if (IsA(node, OidList))
appendStringInfo(str, " %u", lfirst_oid(lc));
+ else if (IsA(node, XidList))
+ appendStringInfo(str, " %u", lfirst_xid(lc));
else
elog(ERROR, "unrecognized list node type: %d",
(int) node->type);
diff --git a/src/backend/replication/pgoutput/pgoutput.c b/src/backend/replication/pgoutput/pgoutput.c
index 8deae57143..2cbca4a087 100644
--- a/src/backend/replication/pgoutput/pgoutput.c
+++ b/src/backend/replication/pgoutput/pgoutput.c
@@ -1923,15 +1923,7 @@ init_rel_sync_cache(MemoryContext cachectx)
static bool
get_schema_sent_in_streamed_txn(RelationSyncEntry *entry, TransactionId xid)
{
- ListCell *lc;
-
- foreach(lc, entry->streamed_txns)
- {
- if (xid == (uint32) lfirst_int(lc))
- return true;
- }
-
- return false;
+ return list_member_xid(entry->streamed_txns, xid);
}
/*
@@ -1945,7 +1937,7 @@ set_schema_sent_in_streamed_txn(RelationSyncEntry *entry, TransactionId xid)
oldctx = MemoryContextSwitchTo(CacheMemoryContext);
- entry->streamed_txns = lappend_int(entry->streamed_txns, xid);
+ entry->streamed_txns = lappend_xid(entry->streamed_txns, xid);
MemoryContextSwitchTo(oldctx);
}
@@ -2248,7 +2240,7 @@ cleanup_rel_sync_cache(TransactionId xid, bool is_commit)
*/
foreach(lc, entry->streamed_txns)
{
- if (xid == (uint32) lfirst_int(lc))
+ if (xid == lfirst_xid(lc))
{
if (is_commit)
entry->schema_sent = true;
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index b3b407579b..7ce1fc4deb 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -317,6 +317,7 @@ typedef enum NodeTag
T_List,
T_IntList,
T_OidList,
+ T_XidList,
/*
* TAGS FOR EXTENSIBLE NODES (extensible.h)
diff --git a/src/include/nodes/pg_list.h b/src/include/nodes/pg_list.h
index 2cb9d1371d..66e70263b2 100644
--- a/src/include/nodes/pg_list.h
+++ b/src/include/nodes/pg_list.h
@@ -45,6 +45,7 @@ typedef union ListCell
void *ptr_value;
int int_value;
Oid oid_value;
+ TransactionId xid_value;
} ListCell;
typedef struct List
@@ -169,6 +170,7 @@ list_length(const List *l)
#define lfirst(lc) ((lc)->ptr_value)
#define lfirst_int(lc) ((lc)->int_value)
#define lfirst_oid(lc) ((lc)->oid_value)
+#define lfirst_xid(lc) ((lc)->xid_value)
#define lfirst_node(type,lc) castNode(type, lfirst(lc))
#define linitial(l) lfirst(list_nth_cell(l, 0))
@@ -194,6 +196,7 @@ list_length(const List *l)
#define llast(l) lfirst(list_last_cell(l))
#define llast_int(l) lfirst_int(list_last_cell(l))
#define llast_oid(l) lfirst_oid(list_last_cell(l))
+#define llast_xid(l) lfirst_xid(list_last_cell(l))
#define llast_node(type,l) castNode(type, llast(l))
/*
@@ -202,6 +205,7 @@ list_length(const List *l)
#define list_make_ptr_cell(v) ((ListCell) {.ptr_value = (v)})
#define list_make_int_cell(v) ((ListCell) {.int_value = (v)})
#define list_make_oid_cell(v) ((ListCell) {.oid_value = (v)})
+#define list_make_xid_cell(v) ((ListCell) {.xid_value = (v)})
#define list_make1(x1) \
list_make1_impl(T_List, list_make_ptr_cell(x1))
@@ -248,6 +252,21 @@ list_length(const List *l)
list_make_oid_cell(x3), list_make_oid_cell(x4), \
list_make_oid_cell(x5))
+#define list_make1_xid(x1) \
+ list_make1_impl(T_XidList, list_make_xid_cell(x1))
+#define list_make2_xid(x1,x2) \
+ list_make2_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2))
+#define list_make3_xid(x1,x2,x3) \
+ list_make3_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \
+ list_make_xid_cell(x3))
+#define list_make4_xid(x1,x2,x3,x4) \
+ list_make4_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \
+ list_make_xid_cell(x3), list_make_xid_cell(x4))
+#define list_make5_xid(x1,x2,x3,x4,x5) \
+ list_make5_impl(T_XidList, list_make_xid_cell(x1), list_make_xid_cell(x2), \
+ list_make_xid_cell(x3), list_make_xid_cell(x4), \
+ list_make_xid_cell(x5))
+
/*
* Locate the n'th cell (counting from 0) of the list.
* It is an assertion failure if there is no such cell.
@@ -539,6 +558,7 @@ extern List *list_make5_impl(NodeTag t, ListCell datum1, ListCell datum2,
extern pg_nodiscard List *lappend(List *list, void *datum);
extern pg_nodiscard List *lappend_int(List *list, int datum);
extern pg_nodiscard List *lappend_oid(List *list, Oid datum);
+extern pg_nodiscard List *lappend_xid(List *list, TransactionId datum);
extern pg_nodiscard List *list_insert_nth(List *list, int pos, void *datum);
extern pg_nodiscard List *list_insert_nth_int(List *list, int pos, int datum);
@@ -557,6 +577,7 @@ extern bool list_member(const List *list, const void *datum);
extern bool list_member_ptr(const List *list, const void *datum);
extern bool list_member_int(const List *list, int datum);
extern bool list_member_oid(const List *list, Oid datum);
+extern bool list_member_xid(const List *list, TransactionId datum);
extern pg_nodiscard List *list_delete(List *list, void *datum);
extern pg_nodiscard List *list_delete_ptr(List *list, void *datum);