Implement List support for TransactionId
authorAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 4 Jul 2022 12:52:12 +0000 (14:52 +0200)
committerAlvaro Herrera <alvherre@alvh.no-ip.org>
Mon, 4 Jul 2022 12:52:12 +0000 (14:52 +0200)
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>
src/backend/nodes/list.c
src/backend/nodes/outfuncs.c
src/backend/replication/pgoutput/pgoutput.c
src/include/nodes/nodes.h
src/include/nodes/pg_list.h

index f843f861ef8024b9df404072a78d8ad60bfa8a3b..9d8f4fd5c7cab5ce75d91dfb386f8577659901e8 100644 (file)
@@ -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)
@@ -383,6 +385,24 @@ lappend_oid(List *list, Oid datum)
    return list;
 }
 
+/*
+ * 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
@@ -714,6 +734,26 @@ list_member_oid(const List *list, Oid datum)
    return false;
 }
 
+/*
+ * 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.
  *
index ce129155925965903e168a327384cbb71da8f178..4315c530804ea143e9cd600d22842c0ef5c63724 100644 (file)
@@ -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);
index 8deae5714333ac90cf30c21a03e8633a22878dfe..2cbca4a08708cd82b255f731cd296e086ffaae6e 100644 (file)
@@ -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;
index b3b407579b06b8f2be2abcdc01083a44fb904f8d..7ce1fc4deb6e05bd1e25ffdec80f42730884e955 100644 (file)
@@ -317,6 +317,7 @@ typedef enum NodeTag
    T_List,
    T_IntList,
    T_OidList,
+   T_XidList,
 
    /*
     * TAGS FOR EXTENSIBLE NODES (extensible.h)
index 2cb9d1371d97fe96404f055b22f4552395104aad..66e70263b2f4b84d16d9d7e815a851d683e44278 100644 (file)
@@ -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);