From 3c8db20981ab74a562b14fb60143559cd614dfb2 Mon Sep 17 00:00:00 2001
From: "kuroda.hayato%40jp.fujitsu.com" <kuroda.hayato@jp.fujitsu.com>
Date: Wed, 18 May 2022 04:56:18 +0000
Subject: [PATCH 2/2] add doc

---
 doc/src/sgml/catalogs.sgml | 296 +++++++++++++++++++++++++++++++++++++
 doc/src/sgml/filelist.sgml |   1 +
 doc/src/sgml/func.sgml     |  54 +++++++
 doc/src/sgml/lrg.sgml      | 294 ++++++++++++++++++++++++++++++++++++
 doc/src/sgml/postgres.sgml |   1 +
 5 files changed, 646 insertions(+)
 create mode 100644 doc/src/sgml/lrg.sgml

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index a533a2153e..29abc04fab 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -200,6 +200,22 @@
       <entry>metadata for large objects</entry>
      </row>
 
+     <row>
+      <entry><link linkend="catalog-pg-lrg-info"><structname>pg_lrg_info</structname></link></entry>
+      <entry>logical replication group</entry>
+     </row>
+
+     <row>
+      <entry><link linkend="catalog-pg-lrg-nodes"><structname>pg_lrg_nodes</structname></link></entry>
+      <entry>logical replication group</entry>
+     </row>
+
+     <row>
+      <entry><link linkend="catalog-pg-lrg-pub"><structname>pg_lrg_pub</structname></link></entry>
+      <entry>logical replication group</entry>
+     </row>
+
+
      <row>
       <entry><link linkend="catalog-pg-namespace"><structname>pg_namespace</structname></link></entry>
       <entry>schemas</entry>
@@ -4960,6 +4976,286 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
   </table>
  </sect1>
 
+ <sect1 id="catalog-pg-lrg-info">
+  <title><structname>pg_lrg_info</structname></title>
+
+  <indexterm zone="catalog-pg-lrg-info">
+   <primary>pg_lrg_info</primary>
+  </indexterm>
+  <para>
+   test
+  </para>
+
+  <table>
+   <title><structname>pg_lrg_info</structname> Columns</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>oid</structfield> <type>oid</type>
+      </para>
+      <para>
+       Row identifier
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>groupname</structfield> <type>name</type>
+      </para>
+      <para>
+       Name of the group
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>puballtables</structfield> <type>bool</type>
+      </para>
+      <para>
+       The type of publication
+      </para></entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
+ </sect1>
+
+ <sect1 id="catalog-pg-lrg-nodes">
+  <title><structname>pg_lrg_nodes</structname></title>
+
+  <indexterm zone="catalog-pg-lrg-nodes">
+   <primary>pg_lrg_nodes</primary>
+  </indexterm>
+  <para>
+   test
+  </para>
+
+  <table>
+   <title><structname>pg_lrg_nodes</structname> Columns</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>oid</structfield> <type>oid</type>
+      </para>
+      <para>
+       Row identifier
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>nodeid</structfield> <type>name</type>
+      </para>
+      <para>
+       Identifier of this node
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>groupid</structfield> <type>oid</type>
+       (references <link linkend="catalog-pg-lrg-info"><structname>pg_lrg_info</structname></link>.<structfield>oid</structfield>)
+      </para>
+      <para>
+       attached group
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>dbid</structfield> <type>oid</type>
+       (references <link linkend="catalog-pg-database"><structname>pg_database</structname></link>.<structfield>oid</structfield>)
+      </para>
+      <para>
+       database
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>status</structfield> <type>int</type>
+      </para>
+      <para>
+       status
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>nodename</structfield> <type>name</type>
+      </para>
+      <para>
+       Name of this node
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>localconn</structfield> <type>name</type>
+      </para>
+      <para>
+       connection string for this node
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>upstreamconn</structfield> <type>name</type>
+      </para>
+      <para>
+       connection string for upstream node
+      </para></entry>
+     </row>
+
+    </tbody>
+   </tgroup>
+  </table>
+ </sect1>
+
+ <sect1 id="catalog-pg-lrg-pub">
+  <title><structname>pg_lrg_pub</structname></title>
+
+  <indexterm zone="catalog-pg-lrg-pub">
+   <primary>pg_lrg_pub</primary>
+  </indexterm>
+  <para>
+   test
+  </para>
+
+  <table>
+   <title><structname>pg_lrg_pub</structname> Columns</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>oid</structfield> <type>oid</type>
+      </para>
+      <para>
+       Row identifier
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>groupid</structfield> <type>oid</type>
+       (references <link linkend="catalog-pg-lrg-info"><structname>pg_lrg_info</structname></link>.<structfield>oid</structfield>)
+      </para>
+      <para>
+       attached group
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>pubid</structfield> <type>oid</type>
+       (references <link linkend="catalog-pg-publication"><structname>pg_publication</structname></link>.<structfield>oid</structfield>)
+      </para>
+      <para>
+       publication
+      </para></entry>
+     </row>
+
+
+    </tbody>
+   </tgroup>
+  </table>
+ </sect1>
+
+
+ <sect1 id="catalog-pg-lrg-sub">
+  <title><structname>pg_lrg_sub</structname></title>
+
+  <indexterm zone="catalog-pg-lrg-sub">
+   <primary>pg_lrg_sub</primary>
+  </indexterm>
+  <para>
+   test
+  </para>
+
+  <table>
+   <title><structname>pg_lrg_sub</structname> Columns</title>
+   <tgroup cols="1">
+    <thead>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       Column Type
+      </para>
+      <para>
+       Description
+      </para></entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>oid</structfield> <type>oid</type>
+      </para>
+      <para>
+       Row identifier
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>groupid</structfield> <type>oid</type>
+       (references <link linkend="catalog-pg-lrg-info"><structname>pg_lrg_info</structname></link>.<structfield>oid</structfield>)
+      </para>
+      <para>
+       attached group
+      </para></entry>
+     </row>
+
+     <row>
+      <entry role="catalog_table_entry"><para role="column_definition">
+       <structfield>subid</structfield> <type>oid</type>
+       (references <link linkend="catalog-pg-subscription"><structname>pg_subscription</structname></link>.<structfield>oid</structfield>)
+      </para>
+      <para>
+       subscription
+      </para></entry>
+     </row>
+
+
+    </tbody>
+   </tgroup>
+  </table>
+ </sect1>
 
  <sect1 id="catalog-pg-namespace">
   <title><structname>pg_namespace</structname></title>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 40ef5f7ffc..8be17a652e 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -49,6 +49,7 @@
 <!ENTITY wal           SYSTEM "wal.sgml">
 <!ENTITY logical-replication    SYSTEM "logical-replication.sgml">
 <!ENTITY jit    SYSTEM "jit.sgml">
+<!ENTITY lrg    SYSTEM "lrg.sgml">
 
 <!-- programmer's guide -->
 <!ENTITY bgworker   SYSTEM "bgworker.sgml">
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 85ecc639fd..38eac617fa 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -29233,6 +29233,60 @@ postgres=# SELECT * FROM pg_walfile_name_offset((pg_backup_stop()).lsn);
 
   </sect2>
 
+  <sect2 id="functions-lrg">
+   <title>Logical Replication Group Management Functions</title>
+
+   <para>
+    The functions shown
+    in <xref linkend="functions-lrg-table"/> are for
+    controlling and interacting with logical replication groups.
+   </para>
+
+   <table id="functions-lrg-table">
+    <title>LRG Management Functions</title>
+    <tgroup cols="1">
+     <thead>
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        Function
+       </para>
+       <para>
+        Description
+       </para></entry>
+      </row>
+     </thead>
+
+     <tbody>
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <indexterm>
+         <primary></primary>
+        </indexterm>
+        <function>lrg_create</function> ( <parameter>group_name</parameter> <type>name</type>, <parameter>publication_type</parameter> <type>text</type>, <parameter>local_connstring</parameter> <type>text</type>, <parameter>node_name</parameter> <type>name</type>)
+        <returnvalue></returnvalue>
+       </para>
+       <para>
+        creates a group.
+       </para></entry>
+      </row>
+      <row>
+       <entry role="func_table_entry"><para role="func_signature">
+        <indexterm>
+         <primary></primary>
+        </indexterm>
+        <function>lrg_node_attach</function> ( <parameter>group_name</parameter> <type>name</type>, <parameter>local_connstring</parameter> <type>text</type>, <parameter>upstream_connstring</parameter> <type>text</type>, <parameter>node_name</parameter> <type>name</type>)
+        <returnvalue></returnvalue>
+       </para>
+       <para>
+        attach to a group.
+       </para></entry>
+      </row>
+     </tbody>
+    </tgroup>
+   </table>
+
+  </sect2>
+
   <sect2 id="functions-admin-dbobject">
    <title>Database Object Management Functions</title>
 
diff --git a/doc/src/sgml/lrg.sgml b/doc/src/sgml/lrg.sgml
new file mode 100644
index 0000000000..307ccfb61a
--- /dev/null
+++ b/doc/src/sgml/lrg.sgml
@@ -0,0 +1,294 @@
+<!-- doc/src/sgml/lrg.sgml -->
+ <chapter id="lrg">
+  <title>Logical Replication Group (LRG)</title>
+
+  <indexterm zone="lrg">
+   <primary>logical replication group</primary>
+  </indexterm>
+
+ <para>
+  Logical Replication Group(LRG) provides an easy way for constructing
+  N-directional logical replicaiton systems. Advantages of LRG are
+
+   <itemizedlist>
+    <listitem>
+     <para>
+      Allowing load balancing
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Allowing rolling updates of nodes
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Improving the availability of the system
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Improving performance
+     </para>
+    </listitem>
+   </itemizedlist>
+
+ </para>
+
+  <sect1 id="lrg-concepts">
+   <title>Concepts</title>
+   <para>
+    In this section terminology for LRG is defined.
+   </para>
+   <sect2>
+    <title>Node Group</title>
+    <para>
+     Node group is a group that participant nodes have same tables and send/receive their data changes.
+     Note that each node in a group must be connected to all other nodes in that group.
+     LRG accomplishes such a group by creating publications and subscriptions on nodes.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>Upstream node</title>
+    <para>
+     Upstream node is a node that belongs to a group, and it must be specified when a node attaches to the group.
+     It is not special and arbitrary participants can be used as that.
+     The attaching node will copy data from the upstream.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>lrg launcher</title>
+    <para>
+     Lrg launcher is a background worker that is registered at postmaster startup.
+     This will be registered when <varname>max_logical_replication_workers</varname> is not equal to zero.
+     This process sometimes seeks pg_database, and it launches lrg worker associated with the database.
+    </para>
+   </sect2>
+
+   <sect2>
+    <title>lrg worker</title>
+    <para>
+     Lrg worker is a background worker that is registered by the lrg launcher.
+     This process is associated with a specific database, and performs all operations related to the LRG feature.
+     If this database is not a member of any node groups, this process will exit immediately.
+    </para>
+   </sect2>
+
+  </sect1>
+
+  <sect1 id="lrg-interface">
+   <title>LRG SQL interface</title>
+    <para>
+     See <xref linkend="functions-lrg"/> for detailed documentation on
+     SQL-level APIs for interacting with logical replication group.
+    </para>
+  </sect1>
+
+  <sect1 id="lrg-catalog">
+   <title>System Catalogs related to LRG</title>
+    <para>
+     Following catalogs are used for LRG.
+
+    <itemizedlist>
+     <listitem>
+      <para>
+       <link linkend="catalog-pg-lrg-info"><structname>pg_lrg_info</structname></link>,
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       <link linkend="catalog-pg-lrg-nodes"><structname>pg_lrg_nodes</structname></link>,
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       <link linkend="catalog-pg-lrg-pub"><structname>pg_lrg_pub</structname></link>,
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       <link linkend="catalog-pg-lrg-sub"><structname>pg_lrg_sub</structname></link>
+      </para>
+     </listitem>
+    </itemizedlist>
+    </para>
+
+  </sect1>
+
+  <sect1 id="lrg-restriction">
+   <title>Restrictions</title>
+    <para>
+     LRG currently has the following restrictions or missing functionality.
+    <itemizedlist>
+     <listitem>
+      <para>
+       Each node can attach only one node set at a time.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       All tables must be shard in the database.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       LRG does not provide any mechanism for conflict handling (e.g. PK violations).
+       Avoiding conflicts is the user responsibility.
+      </para>
+     </listitem>
+    </itemizedlist>
+    </para>
+  </sect1>
+
+  <sect1 id="lrg-configuration">
+   <title>Configuration</title>
+    <para>
+     LRG will create a publication and subscriptions on each node,
+     that number of subscribers is the number of participants minus one. Therefore LRG requires
+     several configuration options.
+    </para>
+
+    <itemizedlist>
+     <listitem>
+      <para>
+       <varname>wal_level</varname> must be <literal>logical</literal>.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       <varname>max_replication_slots</varname> must be set to at least the number of participants.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       <varname>max_wal_senders</varname> must be set to at least same as <varname>max_replication_slots</varname>.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       <varname>max_logical_replication_workers</varname> must be larger than the number of participants.
+      </para>
+     </listitem>
+     <listitem>
+      <para>
+       <varname>max_worker_processes</varname> must be larger that <literal>max_logical_replication_workers</literal>.
+      </para>
+     </listitem>
+    </itemizedlist>
+  </sect1>
+
+  <sect1 id="lrg-example">
+   <title>Example</title>
+   <para>
+    The following example demonstrates constructing N-directional logical replication group.
+    Assuming that there are three nodes, called Node1, Node2, Node3, and they can connect each other.
+    In the example they are in the same machine.
+   </para>
+
+   <para>
+    At first, a node group must be created. Here it will be created on Node1.
+   </para>
+<programlisting>
+postgres=# -- Create a node group 'testgroup', and attach to it as 'testnode1'
+postgres=# SELECT lrg_create('testgroup', 'FOR ALL TABLES', 'port=5431 dbname=postgres', 'testnode1');
+ lrg_create
+------------
+
+(1 row)
+</programlisting>
+
+   <para>
+    Information of the group and nodes can check via system catalogs,
+    like <link linkend="catalog-pg-lrg-nodes"><structname>pg_lrg_nodes</structname></link>.
+   </para>
+<programlisting>
+postgres=# SELECT * FROM pg_lrg_info ;
+  oid  | groupname | puballtables
+-------+-----------+--------------
+ 16384 | testgroup | t
+(1 row)
+
+postgres=# SELECT * FROM pg_lrg_nodes;
+  oid  |        nodeid        | groupid | dbid | status | nodename  |         localconn         | upstreamconn
+-------+----------------------+---------+------+--------+-----------+---------------------------+--------------
+ 16385 | 70988980716274892555 |   16384 |    5 |      3 | testnode1 | port=5431 dbname=postgres |
+(1 row)
+</programlisting>
+
+   <para>
+    Next Node2 can attach the created group testgroup. Note that the connection string for Node1 must be specified.
+   </para>
+
+<programlisting>
+postgres=# -- Attach to 'testgroup' as 'testnode2'
+postgres=# SELECT lrg_node_attach('testgroup', 'port=5432 dbname=postgres', 'port=5431 dbname=postgres', 'testnode2');
+ lrg_node_attach
+-----------------
+
+(1 row)
+</programlisting>
+
+   <para>
+    The status of all nodes can check via pg_lrg_nodes. Following tuples will be found on both nodes.
+   </para>
+
+<programlisting>
+postgres=# SELECT * FROM pg_lrg_info ;
+  oid  | groupname | puballtables
+-------+-----------+--------------
+ 16384 | testgroup | t
+(1 row)
+
+postgres=# SELECT * FROM pg_lrg_nodes;
+  oid  |        nodeid        | groupid | dbid | status | nodename  |         localconn         |       upstreamconn
+-------+----------------------+---------+------+--------+-----------+---------------------------+---------------------------
+ 16385 | 70989229890284027935 |   16384 |    5 |      3 | testnode2 | port=5432 dbname=postgres | port=5431 dbname=postgres
+ 16386 | 70988980716274892555 |   16385 |    5 |      3 | testnode1 | port=5431 dbname=postgres |
+(2 rows)
+</programlisting>
+
+   <para>
+    Now Node1 and Node2 has same contents about LRG system catalogs,
+    so ether of them can be specified as an upstream node.
+    In below example Node2 is used as upstream for attaching a new node.
+   </para>
+
+<programlisting>
+postgres=# -- Attach to 'testgroup' as 'testode3', and data will be copied from Node2
+postgres=# SELECT lrg_node_attach('testgroup', 'port=5433 dbname=postgres', 'port=5432 dbname=postgres', 'testnode3');
+ lrg_node_attach
+-----------------
+
+(1 row)
+</programlisting>
+
+   <para>
+    Finally pg_lrg_info and pg_lrg_nodes will be like:
+   </para>
+
+<programlisting>
+postgres=# SELECT * FROM pg_lrg_info ;
+  oid  | groupname | puballtables
+-------+-----------+--------------
+ 16384 | testgroup | t
+(1 row)
+
+postgres=# SELECT * FROM pg_lrg_nodes;
+  oid  |        nodeid        | groupid | dbid | status | nodename  |         localconn         |       upstreamconn
+-------+----------------------+---------+------+--------+-----------+---------------------------+---------------------------
+ 16385 | 70989243367269230745 |   16384 |    5 |      3 | testnode3 | port=5433 dbname=postgres | port=5432 dbname=postgres
+ 16386 | 70989229890284027935 |   16385 |    5 |      3 | testnode2 | port=5432 dbname=postgres | port=5431 dbname=postgres
+ 16387 | 70988980716274892555 |   16385 |    5 |      3 | testnode1 | port=5431 dbname=postgres |
+(3 rows)
+</programlisting>
+
+   <para>
+    Now all nodes publish their changes, and they subscribe them. If a tuple inserted on Node1,
+    the data will be also found on Node2 and Node3.
+   </para>
+
+  </sect1>
+
+ </chapter>
\ No newline at end of file
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 0b60e46d69..bcea47fdc9 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -172,6 +172,7 @@ break is not needed in a wider output rendering.
   &logical-replication;
   &jit;
   &regress;
+  &lrg;
 
  </part>
 
-- 
2.27.0

