public inbox for [email protected]  
help / color / mirror / Atom feed
[PATCH 03/10] Make sure published XIDs are persistent
7+ messages / 5 participants
[nested] [flat]

* [PATCH 03/10] Make sure published XIDs are persistent
@ 2021-03-08 06:43 Kyotaro Horiguchi <[email protected]>
  0 siblings, 0 replies; 7+ messages in thread

From: Kyotaro Horiguchi @ 2021-03-08 06:43 UTC (permalink / raw)

pg_xact_status() premises that XIDs obtained by
pg_current_xact_id(_if_assigned)() are persistent beyond a crash. But
XIDs are not guaranteed to go beyond WAL buffers before commit and
thus XIDs may vanish if server crashes before commit. This patch
guarantees the XID shown by the functions to be flushed out to disk.

Copied from: https://www.postgresql.org/message-id/20210308.173242.463790587797836129.horikyota.ntt%40gmail.com
---
 src/backend/access/transam/xact.c | 55 +++++++++++++++++++++++++------
 src/backend/access/transam/xlog.c |  2 +-
 src/backend/utils/adt/xid8funcs.c | 12 ++++++-
 src/include/access/xact.h         |  3 +-
 4 files changed, 59 insertions(+), 13 deletions(-)

diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c
index 6395a9b240..38e978d238 100644
--- a/src/backend/access/transam/xact.c
+++ b/src/backend/access/transam/xact.c
@@ -201,7 +201,7 @@ typedef struct TransactionStateData
 	int			prevSecContext; /* previous SecurityRestrictionContext */
 	bool		prevXactReadOnly;	/* entry-time xact r/o state */
 	bool		startedInRecovery;	/* did we start in recovery? */
-	bool		didLogXid;		/* has xid been included in WAL record? */
+	XLogRecPtr 	minLSN;			/* LSN needed to reach to record the xid */
 	int			parallelModeLevel;	/* Enter/ExitParallelMode counter */
 	bool		chain;			/* start a new block after this one */
 	bool		assigned;		/* assigned to top-level XID */
@@ -520,14 +520,46 @@ GetCurrentFullTransactionIdIfAny(void)
  *	MarkCurrentTransactionIdLoggedIfAny
  *
  * Remember that the current xid - if it is assigned - now has been wal logged.
+ *
+ * upto is the LSN up to which we need to flush WAL to ensure the current xid
+ * to be persistent. See EnsureCurrentTransactionIdLogged().
  */
 void
-MarkCurrentTransactionIdLoggedIfAny(void)
+MarkCurrentTransactionIdLoggedIfAny(XLogRecPtr upto)
 {
-	if (FullTransactionIdIsValid(CurrentTransactionState->fullTransactionId))
-		CurrentTransactionState->didLogXid = true;
+	if (FullTransactionIdIsValid(CurrentTransactionState->fullTransactionId) &&
+		XLogRecPtrIsInvalid(CurrentTransactionState->minLSN))
+		CurrentTransactionState->minLSN = upto;
 }
 
+/*
+ *	EnsureCurrentTransactionIdLogged
+ *
+ * Make sure that the current top XID is WAL-logged.
+ */
+void
+EnsureTopTransactionIdLogged(void)
+{
+	/*
+	 * We need at least one WAL record for the current top transaction to be
+	 * flushed out.  Write one if we don't have one yet.
+	 */
+	if (XLogRecPtrIsInvalid(TopTransactionStateData.minLSN))
+	{
+		xl_xact_assignment xlrec;
+
+		xlrec.xtop = XidFromFullTransactionId(XactTopFullTransactionId);
+		Assert(TransactionIdIsValid(xlrec.xtop));
+		xlrec.nsubxacts = 0;
+
+		XLogBeginInsert();
+		XLogRegisterData((char *) &xlrec, MinSizeOfXactAssignment);
+		TopTransactionStateData.minLSN =
+			XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT);
+	}
+
+	XLogFlush(TopTransactionStateData.minLSN);
+}
 
 /*
  *	GetStableLatestTransactionId
@@ -616,14 +648,14 @@ AssignTransactionId(TransactionState s)
 	 * When wal_level=logical, guarantee that a subtransaction's xid can only
 	 * be seen in the WAL stream if its toplevel xid has been logged before.
 	 * If necessary we log an xact_assignment record with fewer than
-	 * PGPROC_MAX_CACHED_SUBXIDS. Note that it is fine if didLogXid isn't set
+	 * PGPROC_MAX_CACHED_SUBXIDS. Note that it is fine if minLSN isn't set
 	 * for a transaction even though it appears in a WAL record, we just might
 	 * superfluously log something. That can happen when an xid is included
 	 * somewhere inside a wal record, but not in XLogRecord->xl_xid, like in
 	 * xl_standby_locks.
 	 */
 	if (isSubXact && XLogLogicalInfoActive() &&
-		!TopTransactionStateData.didLogXid)
+		XLogRecPtrIsInvalid(TopTransactionStateData.minLSN))
 		log_unknown_top = true;
 
 	/*
@@ -693,6 +725,7 @@ AssignTransactionId(TransactionState s)
 			log_unknown_top)
 		{
 			xl_xact_assignment xlrec;
+			XLogRecPtr		   endptr;
 
 			/*
 			 * xtop is always set by now because we recurse up transaction
@@ -707,11 +740,13 @@ AssignTransactionId(TransactionState s)
 			XLogRegisterData((char *) unreportedXids,
 							 nUnreportedXids * sizeof(TransactionId));
 
-			(void) XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT);
+			endptr = XLogInsert(RM_XACT_ID, XLOG_XACT_ASSIGNMENT);
 
 			nUnreportedXids = 0;
-			/* mark top, not current xact as having been logged */
-			TopTransactionStateData.didLogXid = true;
+
+			/* set minLSN of top, not of current xact if not yet */
+			if (XLogRecPtrIsInvalid(TopTransactionStateData.minLSN))
+				TopTransactionStateData.minLSN = endptr;
 		}
 	}
 }
@@ -2022,7 +2057,7 @@ StartTransaction(void)
 	 * initialize reported xid accounting
 	 */
 	nUnreportedXids = 0;
-	s->didLogXid = false;
+	s->minLSN = InvalidXLogRecPtr;
 
 	/*
 	 * must initialize resource-management stuff first
diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c
index 15da91a8dd..6eb46ea8a7 100644
--- a/src/backend/access/transam/xlog.c
+++ b/src/backend/access/transam/xlog.c
@@ -1172,7 +1172,7 @@ XLogInsertRecord(XLogRecData *rdata,
 	 */
 	WALInsertLockRelease();
 
-	MarkCurrentTransactionIdLoggedIfAny();
+	MarkCurrentTransactionIdLoggedIfAny(EndPos);
 
 	END_CRIT_SECTION();
 
diff --git a/src/backend/utils/adt/xid8funcs.c b/src/backend/utils/adt/xid8funcs.c
index cc2b4ac797..992482f8c8 100644
--- a/src/backend/utils/adt/xid8funcs.c
+++ b/src/backend/utils/adt/xid8funcs.c
@@ -357,6 +357,8 @@ bad_format:
 Datum
 pg_current_xact_id(PG_FUNCTION_ARGS)
 {
+	FullTransactionId xid;
+
 	/*
 	 * Must prevent during recovery because if an xid is not assigned we try
 	 * to assign one, which would fail. Programs already rely on this function
@@ -365,7 +367,12 @@ pg_current_xact_id(PG_FUNCTION_ARGS)
 	 */
 	PreventCommandDuringRecovery("pg_current_xact_id()");
 
-	PG_RETURN_FULLTRANSACTIONID(GetTopFullTransactionId());
+	xid = GetTopFullTransactionId();
+
+	/* the XID is going to be published, make sure it is psersistent */
+	EnsureTopTransactionIdLogged();
+
+	PG_RETURN_FULLTRANSACTIONID(xid);
 }
 
 /*
@@ -380,6 +387,9 @@ pg_current_xact_id_if_assigned(PG_FUNCTION_ARGS)
 	if (!FullTransactionIdIsValid(topfxid))
 		PG_RETURN_NULL();
 
+	/* the XID is going to be published, make sure it is psersistent */
+	EnsureTopTransactionIdLogged();
+
 	PG_RETURN_FULLTRANSACTIONID(topfxid);
 }
 
diff --git a/src/include/access/xact.h b/src/include/access/xact.h
index 34cfaf542c..a61e4d6da5 100644
--- a/src/include/access/xact.h
+++ b/src/include/access/xact.h
@@ -386,7 +386,8 @@ extern FullTransactionId GetTopFullTransactionId(void);
 extern FullTransactionId GetTopFullTransactionIdIfAny(void);
 extern FullTransactionId GetCurrentFullTransactionId(void);
 extern FullTransactionId GetCurrentFullTransactionIdIfAny(void);
-extern void MarkCurrentTransactionIdLoggedIfAny(void);
+extern void MarkCurrentTransactionIdLoggedIfAny(XLogRecPtr upto);
+extern void EnsureTopTransactionIdLogged(void);
 extern bool SubTransactionIsActive(SubTransactionId subxid);
 extern CommandId GetCurrentCommandId(bool used);
 extern void SetParallelStartTimestamps(TimestampTz xact_ts, TimestampTz stmt_ts);
-- 
2.17.0


--XsQoSWH+UP9D9v3l
Content-Type: text/x-diff; charset=us-ascii
Content-Disposition: attachment;
 filename="0004-wal_compression_method-default-to-zlib.patch"



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: documentation structure
@ 2024-03-21 13:38 Tom Lane <[email protected]>
  2024-03-21 14:31 ` Re: documentation structure Robert Haas <[email protected]>
  0 siblings, 1 reply; 7+ messages in thread

From: Tom Lane @ 2024-03-21 13:38 UTC (permalink / raw)
  To: Robert Haas <[email protected]>; +Cc: Alvaro Herrera <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers

Robert Haas <[email protected]> writes:
> Well, I suppose I thought it was a good idea because (1) we don't seem
> to have any existing precedent for file-per-sect1 rather than
> file-per-chapter and (2) all of the per-AM files combined are less
> than 20% of the size of func.sgml.

We have done (1) in places, eg. json.sgml, array.sgml,
rangetypes.sgml, rowtypes.sgml, and the bulk of extend.sgml is split
out into xaggr, xfunc, xindex, xoper, xtypes.  I'd be the first to
concede it's a bit haphazard, but it's not like there's no precedent.

As for (2), func.sgml likely should have been split years ago.

> But, OK, if you want to establish a new paradigm here, sure. I see two
> ways to do it. We can either put the <chapter> tag directly in
> postgres.sgml, or I can still create a new indextypes.sgml and put
> &btree; etc. inside of it. Which way do you prefer?

I'd follow the extend.sgml precedent: have a file corresponding to the
chapter and containing any top-level text we need, then that includes
a file per sect1.

			regards, tom lane






^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: documentation structure
  2024-03-21 13:38 Re: documentation structure Tom Lane <[email protected]>
@ 2024-03-21 14:31 ` Robert Haas <[email protected]>
  2024-03-21 16:16   ` Re: documentation structure Robert Haas <[email protected]>
  2024-03-21 16:42   ` Re: documentation structure Alvaro Herrera <[email protected]>
  2024-03-21 23:40   ` Re: documentation structure Peter Eisentraut <[email protected]>
  0 siblings, 3 replies; 7+ messages in thread

From: Robert Haas @ 2024-03-21 14:31 UTC (permalink / raw)
  To: Tom Lane <[email protected]>; +Cc: Alvaro Herrera <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers

On Thu, Mar 21, 2024 at 9:38 AM Tom Lane <[email protected]> wrote:
> I'd follow the extend.sgml precedent: have a file corresponding to the
> chapter and containing any top-level text we need, then that includes
> a file per sect1.

OK, here's a new patch set. I've revised 0003 and 0004 to use this
approach, and I've added a new 0005 that does essentially the same
thing for the PL chapters.

0001 and 0002 are changed. Should 0002 use the include-an-entity
approach as well?

-- 
Robert Haas
EDB: http://www.enterprisedb.com


Attachments:

  [application/octet-stream] v2-0004-docs-Consolidate-into-new-WAL-for-Extensions-chap.patch (3.2K, ../../CA+Tgmoaf2ziTh9Z36hdBA47VwoQa8GG_EmvdN8PN3eKygECTKQ@mail.gmail.com/2-v2-0004-docs-Consolidate-into-new-WAL-for-Extensions-chap.patch)
  download | inline diff:
From bee277b6fda299e510beacf47db10493ef689f76 Mon Sep 17 00:00:00 2001
From: Robert Haas <[email protected]>
Date: Wed, 20 Mar 2024 12:12:48 -0400
Subject: [PATCH v2 4/5] docs: Consolidate into new "WAL for Extensions"
 chapter.

Previously, we had consecutive, very short chapters called "Generic
WAL" and "Custom WAL Resource Managers," explaining different approaches
to the same problem. Merge them into a single chapter.

Rather than actually combining all of the SGML into a single file,
keep one file per <sect1>, and add a glue file that includes all
of them.
---
 doc/src/sgml/custom-rmgr.sgml        | 4 ++--
 doc/src/sgml/filelist.sgml           | 1 +
 doc/src/sgml/generic-wal.sgml        | 4 ++--
 doc/src/sgml/postgres.sgml           | 3 +--
 doc/src/sgml/wal-for-extensions.sgml | 9 +++++++++
 5 files changed, 15 insertions(+), 6 deletions(-)
 create mode 100644 doc/src/sgml/wal-for-extensions.sgml

diff --git a/doc/src/sgml/custom-rmgr.sgml b/doc/src/sgml/custom-rmgr.sgml
index 0d98229295..13a5a6a5b1 100644
--- a/doc/src/sgml/custom-rmgr.sgml
+++ b/doc/src/sgml/custom-rmgr.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/custom-rmgr.sgml -->
 
-<chapter id="custom-rmgr">
+<sect1 id="custom-rmgr">
  <title>Custom WAL Resource Managers</title>
 
  <para>
@@ -102,4 +102,4 @@ extern void RegisterCustomRmgr(RmgrId rmid, const RmgrData *rmgr);
     the custom WAL records, which may prevent the server from starting.
    </para>
  </note>
-</chapter>
+</sect1>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index b5615e1fce..1bb662c16f 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -106,6 +106,7 @@
 <!ENTITY storage    SYSTEM "storage.sgml">
 <!ENTITY transaction     SYSTEM "xact.sgml">
 <!ENTITY tablesample-method SYSTEM "tablesample-method.sgml">
+<!ENTITY wal-for-extensions SYSTEM "wal-for-extensions.sgml">
 <!ENTITY generic-wal SYSTEM "generic-wal.sgml">
 <!ENTITY custom-rmgr SYSTEM "custom-rmgr.sgml">
 <!ENTITY backup-manifest SYSTEM "backup-manifest.sgml">
diff --git a/doc/src/sgml/generic-wal.sgml b/doc/src/sgml/generic-wal.sgml
index a028856d2e..ba00ddf100 100644
--- a/doc/src/sgml/generic-wal.sgml
+++ b/doc/src/sgml/generic-wal.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/generic-wal.sgml -->
 
-<chapter id="generic-wal">
+<sect1 id="generic-wal">
  <title>Generic WAL Records</title>
 
   <para>
@@ -171,4 +171,4 @@
     </listitem>
    </itemizedlist>
   </para>
-</chapter>
+</sect1>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 0235c0e352..5bc47a9e71 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -255,8 +255,7 @@ break is not needed in a wider output rendering.
   &geqo;
   &tableam;
   &indexam;
-  &generic-wal;
-  &custom-rmgr;
+  &wal-for-extensions;
   &indextypes;
   &storage;
   &transaction;
diff --git a/doc/src/sgml/wal-for-extensions.sgml b/doc/src/sgml/wal-for-extensions.sgml
new file mode 100644
index 0000000000..fbebafb5a9
--- /dev/null
+++ b/doc/src/sgml/wal-for-extensions.sgml
@@ -0,0 +1,9 @@
+<!-- doc/src/sgml/wal-for-extensions.sgml -->
+
+<chapter id="wal-for-extensions">
+ <title>Write Ahead Logging for Extensions</title>
+
+&generic-wal;
+&custom-rmgr;
+
+</chapter>
-- 
2.39.3 (Apple Git-145)



  [application/octet-stream] v2-0002-docs-Demote-Monitoring-Disk-Usage-from-chapter-to.patch (11.7K, ../../CA+Tgmoaf2ziTh9Z36hdBA47VwoQa8GG_EmvdN8PN3eKygECTKQ@mail.gmail.com/3-v2-0002-docs-Demote-Monitoring-Disk-Usage-from-chapter-to.patch)
  download | inline diff:
From adce7677286f48a6971251758b9a78877db1895a Mon Sep 17 00:00:00 2001
From: Robert Haas <[email protected]>
Date: Wed, 20 Mar 2024 10:52:16 -0400
Subject: [PATCH v2 2/5] docs: Demote "Monitoring Disk Usage" from chapter to
 section.

This chapter is very short, and the immediately preceding chapter is
called "Monitoring Database Activity". So, instead of having a
separate chapter for this, make it the last section of the preceding
chapter instead.
---
 doc/src/sgml/diskusage.sgml  | 144 -----------------------------------
 doc/src/sgml/filelist.sgml   |   1 -
 doc/src/sgml/monitoring.sgml | 143 ++++++++++++++++++++++++++++++++++
 doc/src/sgml/postgres.sgml   |   1 -
 4 files changed, 143 insertions(+), 146 deletions(-)
 delete mode 100644 doc/src/sgml/diskusage.sgml

diff --git a/doc/src/sgml/diskusage.sgml b/doc/src/sgml/diskusage.sgml
deleted file mode 100644
index 75467582e4..0000000000
--- a/doc/src/sgml/diskusage.sgml
+++ /dev/null
@@ -1,144 +0,0 @@
-<!-- doc/src/sgml/diskusage.sgml -->
-
-<chapter id="diskusage">
- <title>Monitoring Disk Usage</title>
-
- <para>
-  This chapter discusses how to monitor the disk usage of a
-  <productname>PostgreSQL</productname> database system.
- </para>
-
- <sect1 id="disk-usage">
-  <title>Determining Disk Usage</title>
-
-  <indexterm zone="disk-usage">
-   <primary>disk usage</primary>
-  </indexterm>
-
-  <para>
-   Each table has a primary heap disk file where most of the data is
-   stored. If the table has any columns with potentially-wide values,
-   there also might be a <acronym>TOAST</acronym> file associated with the table,
-   which is used to store values too wide to fit comfortably in the main
-   table (see <xref linkend="storage-toast"/>).  There will be one valid index
-   on the <acronym>TOAST</acronym> table, if present. There also might be indexes
-   associated with the base table.  Each table and index is stored in a
-   separate disk file &mdash; possibly more than one file, if the file would
-   exceed one gigabyte.  Naming conventions for these files are described
-   in <xref linkend="storage-file-layout"/>.
-  </para>
-
-  <para>
-   You can monitor disk space in three ways:
-   using the SQL functions listed in <xref linkend="functions-admin-dbsize"/>,
-   using the <xref linkend="oid2name"/> module, or
-   using manual inspection of the system catalogs.
-   The SQL functions are the easiest to use and are generally recommended.
-   The remainder of this section shows how to do it by inspection of the
-   system catalogs.
-  </para>
-
-  <para>
-   Using <application>psql</application> on a recently vacuumed or analyzed database,
-   you can issue queries to see the disk usage of any table:
-<programlisting>
-SELECT pg_relation_filepath(oid), relpages FROM pg_class WHERE relname = 'customer';
-
- pg_relation_filepath | relpages
-----------------------+----------
- base/16384/16806     |       60
-(1 row)
-</programlisting>
-   Each page is typically 8 kilobytes. (Remember, <structfield>relpages</structfield>
-   is only updated by <command>VACUUM</command>, <command>ANALYZE</command>, and
-   a few DDL commands such as <command>CREATE INDEX</command>.)  The file path name
-   is of interest if you want to examine the table's disk file directly.
-  </para>
-
-  <para>
-   To show the space used by <acronym>TOAST</acronym> tables, use a query
-   like the following:
-<programlisting>
-SELECT relname, relpages
-FROM pg_class,
-     (SELECT reltoastrelid
-      FROM pg_class
-      WHERE relname = 'customer') AS ss
-WHERE oid = ss.reltoastrelid OR
-      oid = (SELECT indexrelid
-             FROM pg_index
-             WHERE indrelid = ss.reltoastrelid)
-ORDER BY relname;
-
-       relname        | relpages
-----------------------+----------
- pg_toast_16806       |        0
- pg_toast_16806_index |        1
-</programlisting>
-  </para>
-
-  <para>
-   You can easily display index sizes, too:
-<programlisting>
-SELECT c2.relname, c2.relpages
-FROM pg_class c, pg_class c2, pg_index i
-WHERE c.relname = 'customer' AND
-      c.oid = i.indrelid AND
-      c2.oid = i.indexrelid
-ORDER BY c2.relname;
-
-      relname      | relpages
--------------------+----------
- customer_id_index |       26
-</programlisting>
-  </para>
-
-  <para>
-   It is easy to find your largest tables and indexes using this
-   information:
-<programlisting>
-SELECT relname, relpages
-FROM pg_class
-ORDER BY relpages DESC;
-
-       relname        | relpages
-----------------------+----------
- bigtable             |     3290
- customer             |     3144
-</programlisting>
-  </para>
- </sect1>
-
- <sect1 id="disk-full">
-  <title>Disk Full Failure</title>
-
-  <para>
-   The most important disk monitoring task of a database administrator
-   is to make sure the disk doesn't become full.  A filled data disk will
-   not result in data corruption, but it might prevent useful activity
-   from occurring. If the disk holding the WAL files grows full, database
-   server panic and consequent shutdown might occur.
-  </para>
-
-  <para>
-   If you cannot free up additional space on the disk by deleting
-   other things, you can move some of the database files to other file
-   systems by making use of tablespaces. See <xref
-   linkend="manage-ag-tablespaces"/> for more information about that.
-  </para>
-
-  <tip>
-   <para>
-    Some file systems perform badly when they are almost full, so do
-    not wait until the disk is completely full to take action.
-   </para>
-  </tip>
-
-  <para>
-   If your system supports per-user disk quotas, then the database
-   will naturally be subject to whatever quota is placed on the user
-   the server runs as.  Exceeding the quota will have the same bad
-   effects as running out of disk space entirely.
-  </para>
- </sect1>
-</chapter>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index b7d1222e3e..f39b4efe38 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -34,7 +34,6 @@
 <!ENTITY backup        SYSTEM "backup.sgml">
 <!ENTITY charset       SYSTEM "charset.sgml">
 <!ENTITY client-auth   SYSTEM "client-auth.sgml">
-<!ENTITY diskusage     SYSTEM "diskusage.sgml">
 <!ENTITY high-availability      SYSTEM "high-availability.sgml">
 <!ENTITY installation  SYSTEM "installation.sgml">
 <!ENTITY targets-meson  SYSTEM "targets-meson.sgml">
diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml
index 8736eac284..eda54b4985 100644
--- a/doc/src/sgml/monitoring.sgml
+++ b/doc/src/sgml/monitoring.sgml
@@ -7282,4 +7282,147 @@ if (TRACE_POSTGRESQL_TRANSACTION_START_ENABLED())
 
  </sect1>
 
+ <sect1 id="diskusage">
+  <title>Monitoring Disk Usage</title>
+
+  <para>
+   This section discusses how to monitor the disk usage of a
+   <productname>PostgreSQL</productname> database system.
+  </para>
+
+  <sect2 id="disk-usage">
+   <title>Determining Disk Usage</title>
+
+   <indexterm zone="disk-usage">
+    <primary>disk usage</primary>
+   </indexterm>
+
+   <para>
+    Each table has a primary heap disk file where most of the data is
+    stored. If the table has any columns with potentially-wide values,
+    there also might be a <acronym>TOAST</acronym> file associated with the table,
+    which is used to store values too wide to fit comfortably in the main
+    table (see <xref linkend="storage-toast"/>).  There will be one valid index
+    on the <acronym>TOAST</acronym> table, if present. There also might be indexes
+    associated with the base table.  Each table and index is stored in a
+    separate disk file &mdash; possibly more than one file, if the file would
+    exceed one gigabyte.  Naming conventions for these files are described
+    in <xref linkend="storage-file-layout"/>.
+   </para>
+
+   <para>
+    You can monitor disk space in three ways:
+    using the SQL functions listed in <xref linkend="functions-admin-dbsize"/>,
+    using the <xref linkend="oid2name"/> module, or
+    using manual inspection of the system catalogs.
+    The SQL functions are the easiest to use and are generally recommended.
+    The remainder of this section shows how to do it by inspection of the
+    system catalogs.
+   </para>
+
+   <para>
+    Using <application>psql</application> on a recently vacuumed or analyzed
+    database, you can issue queries to see the disk usage of any table:
+<programlisting>
+SELECT pg_relation_filepath(oid), relpages FROM pg_class WHERE relname = 'customer';
+
+ pg_relation_filepath | relpages
+----------------------+----------
+ base/16384/16806     |       60
+(1 row)
+</programlisting>
+    Each page is typically 8 kilobytes. (Remember, <structfield>relpages</structfield>
+    is only updated by <command>VACUUM</command>, <command>ANALYZE</command>, and
+    a few DDL commands such as <command>CREATE INDEX</command>.)  The file path name
+    is of interest if you want to examine the table's disk file directly.
+   </para>
+
+   <para>
+    To show the space used by <acronym>TOAST</acronym> tables, use a query
+    like the following:
+<programlisting>
+SELECT relname, relpages
+FROM pg_class,
+     (SELECT reltoastrelid
+      FROM pg_class
+      WHERE relname = 'customer') AS ss
+WHERE oid = ss.reltoastrelid OR
+      oid = (SELECT indexrelid
+             FROM pg_index
+             WHERE indrelid = ss.reltoastrelid)
+ORDER BY relname;
+
+       relname        | relpages
+----------------------+----------
+ pg_toast_16806       |        0
+ pg_toast_16806_index |        1
+</programlisting>
+   </para>
+
+   <para>
+    You can easily display index sizes, too:
+<programlisting>
+SELECT c2.relname, c2.relpages
+FROM pg_class c, pg_class c2, pg_index i
+WHERE c.relname = 'customer' AND
+      c.oid = i.indrelid AND
+      c2.oid = i.indexrelid
+ORDER BY c2.relname;
+
+      relname      | relpages
+-------------------+----------
+ customer_id_index |       26
+</programlisting>
+   </para>
+
+   <para>
+    It is easy to find your largest tables and indexes using this
+    information:
+<programlisting>
+SELECT relname, relpages
+FROM pg_class
+ORDER BY relpages DESC;
+
+       relname        | relpages
+----------------------+----------
+ bigtable             |     3290
+ customer             |     3144
+</programlisting>
+   </para>
+  </sect2>
+
+  <sect2 id="disk-full">
+   <title>Disk Full Failure</title>
+
+   <para>
+    The most important disk monitoring task of a database administrator
+    is to make sure the disk doesn't become full.  A filled data disk will
+    not result in data corruption, but it might prevent useful activity
+    from occurring. If the disk holding the WAL files grows full, database
+    server panic and consequent shutdown might occur.
+   </para>
+
+   <para>
+    If you cannot free up additional space on the disk by deleting
+    other things, you can move some of the database files to other file
+    systems by making use of tablespaces. See <xref
+    linkend="manage-ag-tablespaces"/> for more information about that.
+   </para>
+
+   <tip>
+    <para>
+     Some file systems perform badly when they are almost full, so do
+     not wait until the disk is completely full to take action.
+    </para>
+   </tip>
+
+   <para>
+    If your system supports per-user disk quotas, then the database
+    will naturally be subject to whatever quota is placed on the user
+    the server runs as.  Exceeding the quota will have the same bad
+    effects as running out of disk space entirely.
+   </para>
+  </sect2>
+ </sect1>
+
 </chapter>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 7c234ff1db..73b497bcf8 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -161,7 +161,6 @@ break is not needed in a wider output rendering.
   &backup;
   &high-availability;
   &monitoring;
-  &diskusage;
   &wal;
   &logical-replication;
   &jit;
-- 
2.39.3 (Apple Git-145)



  [application/octet-stream] v2-0003-docs-Merge-separate-chapters-on-built-in-index-AM.patch (14.0K, ../../CA+Tgmoaf2ziTh9Z36hdBA47VwoQa8GG_EmvdN8PN3eKygECTKQ@mail.gmail.com/4-v2-0003-docs-Merge-separate-chapters-on-built-in-index-AM.patch)
  download | inline diff:
From bca9818514d801df1b83fa1d022b6f1d61deafd8 Mon Sep 17 00:00:00 2001
From: Robert Haas <[email protected]>
Date: Wed, 20 Mar 2024 11:51:53 -0400
Subject: [PATCH v2 3/5] docs: Merge separate chapters on built-in index AMs
 into one.

The documetation index is getting very long, which makes it hard
to find things. Since these chapters are all very similar in structure
and content, merging them is a natural way of reducing the size of
the toplevel index.

Rather than actually combining all of the SGML into a single file,
keep one file per <sect1>, and add a glue file that includes all
of them.
---
 doc/src/sgml/brin.sgml       | 22 ++++++++++----------
 doc/src/sgml/btree.sgml      | 32 ++++++++++++++---------------
 doc/src/sgml/filelist.sgml   |  1 +
 doc/src/sgml/gin.sgml        | 40 ++++++++++++++++++------------------
 doc/src/sgml/gist.sgml       | 28 ++++++++++++-------------
 doc/src/sgml/hash.sgml       | 12 +++++------
 doc/src/sgml/indextypes.sgml | 13 ++++++++++++
 doc/src/sgml/postgres.sgml   |  7 +------
 doc/src/sgml/spgist.sgml     | 36 ++++++++++++++++----------------
 9 files changed, 100 insertions(+), 91 deletions(-)
 create mode 100644 doc/src/sgml/indextypes.sgml

diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml
index d898cc4720..64fb520db7 100644
--- a/doc/src/sgml/brin.sgml
+++ b/doc/src/sgml/brin.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/brin.sgml -->
 
-<chapter id="brin">
+<sect1 id="brin">
 <title>BRIN Indexes</title>
 
    <indexterm>
@@ -8,7 +8,7 @@
     <secondary>BRIN</secondary>
    </indexterm>
 
-<sect1 id="brin-intro">
+<sect2 id="brin-intro">
  <title>Introduction</title>
 
  <para>
@@ -64,7 +64,7 @@
   be more precise and more data blocks can be skipped during an index scan.
  </para>
 
- <sect2 id="brin-operation">
+ <sect3 id="brin-operation">
   <title>Index Maintenance</title>
 
   <para>
@@ -136,10 +136,10 @@ LOG:  request for BRIN range summarization for index "brin_wi_idx" page 128 was
    See <xref linkend="functions-admin-index"/> for details.
   </para>
 
- </sect2>
-</sect1>
+ </sect3>
+</sect2>
 
-<sect1 id="brin-builtin-opclasses">
+<sect2 id="brin-builtin-opclasses">
  <title>Built-in Operator Classes</title>
 
  <para>
@@ -743,7 +743,7 @@ LOG:  request for BRIN range summarization for index "brin_wi_idx" page 128 was
   </tgroup>
  </table>
 
-  <sect2 id="brin-builtin-opclasses--parameters">
+  <sect3 id="brin-builtin-opclasses--parameters">
    <title>Operator Class Parameters</title>
 
    <para>
@@ -808,11 +808,11 @@ LOG:  request for BRIN range summarization for index "brin_wi_idx" page 128 was
    </varlistentry>
 
    </variablelist>
-  </sect2>
+  </sect3>
 
-</sect1>
+</sect2>
 
-<sect1 id="brin-extensibility">
+<sect2 id="brin-extensibility">
  <title>Extensibility</title>
 
  <para>
@@ -1340,5 +1340,5 @@ typedef struct BrinOpcInfo
     <literal>float4_minmax_ops</literal> as an example of minmax, and
     <literal>box_inclusion_ops</literal> as an example of inclusion.
  </para>
+</sect2>
 </sect1>
-</chapter>
diff --git a/doc/src/sgml/btree.sgml b/doc/src/sgml/btree.sgml
index be8210286b..2b3997988c 100644
--- a/doc/src/sgml/btree.sgml
+++ b/doc/src/sgml/btree.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/btree.sgml -->
 
-<chapter id="btree">
+<sect1 id="btree">
 <title>B-Tree Indexes</title>
 
    <indexterm>
@@ -8,7 +8,7 @@
     <secondary>B-Tree</secondary>
    </indexterm>
 
-<sect1 id="btree-intro">
+<sect2 id="btree-intro">
  <title>Introduction</title>
 
  <para>
@@ -30,9 +30,9 @@
   btree <acronym>AM</acronym> make use of them.
  </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="btree-behavior">
+<sect2 id="btree-behavior">
  <title>Behavior of B-Tree Operator Classes</title>
 
  <para>
@@ -200,9 +200,9 @@
   planner relies on them for optimization purposes.
  </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="btree-support-funcs">
+<sect2 id="btree-support-funcs">
  <title>B-Tree Support Functions</title>
 
  <para>
@@ -585,9 +585,9 @@ options(<replaceable>relopts</replaceable> <type>local_relopts *</type>) returns
   </varlistentry>
  </variablelist>
 
-</sect1>
+</sect2>
 
-<sect1 id="btree-implementation">
+<sect2 id="btree-implementation">
  <title>Implementation</title>
 
  <para>
@@ -597,7 +597,7 @@ options(<replaceable>relopts</replaceable> <type>local_relopts *</type>) returns
   distribution for a much more detailed, internals-focused description
   of the B-Tree implementation.
  </para>
- <sect2 id="btree-structure">
+ <sect3 id="btree-structure">
   <title>B-Tree Structure</title>
   <para>
    <productname>PostgreSQL</productname> B-Tree indexes are
@@ -627,9 +627,9 @@ options(<replaceable>relopts</replaceable> <type>local_relopts *</type>) returns
    the tree structure by creating a new root page that is one level
    above the original root page.
   </para>
- </sect2>
+ </sect3>
 
- <sect2 id="btree-deletion">
+ <sect3 id="btree-deletion">
   <title>Bottom-up Index Deletion</title>
   <para>
    B-Tree indexes are not directly aware that under MVCC, there might
@@ -731,9 +731,9 @@ options(<replaceable>relopts</replaceable> <type>local_relopts *</type>) returns
    two logical rows whose lifetimes span the same
    <command>VACUUM</command> cycle).
   </para>
- </sect2>
+ </sect3>
 
- <sect2 id="btree-deduplication">
+ <sect3 id="btree-deduplication">
   <title>Deduplication</title>
   <para>
    A duplicate is a leaf page tuple (a tuple that points to a table
@@ -908,7 +908,7 @@ options(<replaceable>relopts</replaceable> <type>local_relopts *</type>) returns
    </itemizedlist>
   </para>
 
- </sect2>
-</sect1>
+ </sect3>
+</sect2>
 
-</chapter>
+</sect1>
diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index f39b4efe38..b5615e1fce 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -84,6 +84,7 @@
 <!ENTITY catalogs   SYSTEM "catalogs.sgml">
 <!ENTITY system-views  SYSTEM "system-views.sgml">
 <!ENTITY geqo       SYSTEM "geqo.sgml">
+<!ENTITY indextypes SYSTEM "indextypes.sgml">
 <!ENTITY btree      SYSTEM "btree.sgml">
 <!ENTITY gist       SYSTEM "gist.sgml">
 <!ENTITY spgist     SYSTEM "spgist.sgml">
diff --git a/doc/src/sgml/gin.sgml b/doc/src/sgml/gin.sgml
index 5bd1efae92..46e87e0132 100644
--- a/doc/src/sgml/gin.sgml
+++ b/doc/src/sgml/gin.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/gin.sgml -->
 
-<chapter id="gin">
+<sect1 id="gin">
 <title>GIN Indexes</title>
 
    <indexterm>
@@ -8,7 +8,7 @@
     <secondary>GIN</secondary>
    </indexterm>
 
-<sect1 id="gin-intro">
+<sect2 id="gin-intro">
  <title>Introduction</title>
 
  <para>
@@ -60,9 +60,9 @@
   information about <acronym>GIN</acronym> on their
   <ulink url="http://www.sai.msu.su/~megera/wiki/Gin">website</ulink>.
  </para>
-</sect1>
+</sect2>
 
-<sect1 id="gin-builtin-opclasses">
+<sect2 id="gin-builtin-opclasses">
  <title>Built-in Operator Classes</title>
 
  <para>
@@ -140,9 +140,9 @@
   See <xref linkend="json-indexing"/> for details.
  </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="gin-extensibility">
+<sect2 id="gin-extensibility">
  <title>Extensibility</title>
 
  <para>
@@ -458,9 +458,9 @@
   though the actual type might be something else depending on the operator.
  </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="gin-implementation">
+<sect2 id="gin-implementation">
  <title>Implementation</title>
 
  <para>
@@ -497,7 +497,7 @@
   </mediaobject>
  </figure>
 
- <sect2 id="gin-fast-update">
+ <sect3 id="gin-fast-update">
   <title>GIN Fast Update Technique</title>
 
   <para>
@@ -535,9 +535,9 @@
    <acronym>GIN</acronym> index.  See <xref linkend="sql-createindex"/>
    for details.
   </para>
- </sect2>
+ </sect3>
 
- <sect2 id="gin-partial-match">
+ <sect3 id="gin-partial-match">
   <title>Partial Match Algorithm</title>
 
   <para>
@@ -554,11 +554,11 @@
    to be searched, or greater than zero if the index key is past the range
    that could match.
   </para>
- </sect2>
+ </sect3>
 
-</sect1>
+</sect2>
 
-<sect1 id="gin-tips">
+<sect2 id="gin-tips">
 <title>GIN Tips and Tricks</title>
 
  <variablelist>
@@ -653,9 +653,9 @@
   </varlistentry>
  </variablelist>
 
-</sect1>
+</sect2>
 
-<sect1 id="gin-limit">
+<sect2 id="gin-limit">
  <title>Limitations</title>
 
  <para>
@@ -667,9 +667,9 @@
   however that null key values contained within a non-null composite item
   or query value are supported.
  </para>
-</sect1>
+</sect2>
 
-<sect1 id="gin-examples">
+<sect2 id="gin-examples">
  <title>Examples</title>
 
  <para>
@@ -709,6 +709,6 @@
   </varlistentry>
  </variablelist>
  </para>
-</sect1>
+</sect2>
 
-</chapter>
+</sect1>
diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml
index 8a19f156d8..3f7df103b8 100644
--- a/doc/src/sgml/gist.sgml
+++ b/doc/src/sgml/gist.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/gist.sgml -->
 
-<chapter id="gist">
+<sect1 id="gist">
 <title>GiST Indexes</title>
 
    <indexterm>
@@ -8,7 +8,7 @@
     <secondary>GiST</secondary>
    </indexterm>
 
-<sect1 id="gist-intro">
+<sect2 id="gist-intro">
  <title>Introduction</title>
 
  <para>
@@ -38,9 +38,9 @@
     <ulink url="http://www.sai.msu.su/~megera/postgres/gist/">web site</ulink>.
   </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="gist-builtin-opclasses">
+<sect2 id="gist-builtin-opclasses">
  <title>Built-in Operator Classes</title>
 
  <para>
@@ -222,9 +222,9 @@ CREATE INDEX ON my_table USING GIST (my_inet_column inet_ops);
 </programlisting>
  </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="gist-extensibility">
+<sect2 id="gist-extensibility">
  <title>Extensibility</title>
 
  <para>
@@ -1260,12 +1260,12 @@ my_stratnum(PG_FUNCTION_ARGS)
    will accumulate for the duration of the operation.
   </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="gist-implementation">
+<sect2 id="gist-implementation">
  <title>Implementation</title>
 
- <sect2 id="gist-buffering-build">
+ <sect3 id="gist-buffering-build">
   <title>GiST Index Build Methods</title>
 
   <para>
@@ -1314,10 +1314,10 @@ my_stratnum(PG_FUNCTION_ARGS)
    is ordered.
   </para>
 
- </sect2>
-</sect1>
+ </sect3>
+</sect2>
 
-<sect1 id="gist-examples">
+<sect2 id="gist-examples">
  <title>Examples</title>
 
  <para>
@@ -1382,6 +1382,6 @@ my_stratnum(PG_FUNCTION_ARGS)
  </variablelist>
  </para>
 
-</sect1>
+</sect2>
 
-</chapter>
+</sect1>
diff --git a/doc/src/sgml/hash.sgml b/doc/src/sgml/hash.sgml
index e35911ebf8..9e69ef91fe 100644
--- a/doc/src/sgml/hash.sgml
+++ b/doc/src/sgml/hash.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/hash.sgml -->
 
-<chapter id="hash-index">
+<sect1 id="hash-index">
 <title>Hash Indexes</title>
 
    <indexterm>
@@ -8,7 +8,7 @@
     <secondary>Hash</secondary>
    </indexterm>
 
-<sect1 id="hash-intro">
+<sect2 id="hash-intro">
  <title>Overview</title>
 
  <para>
@@ -108,9 +108,9 @@
   with rapidly increasing number of rows.
  </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="hash-implementation">
+<sect2 id="hash-implementation">
  <title>Implementation</title>
 
  <para>
@@ -157,6 +157,6 @@
   successfully.
  </para>
 
-</sect1>
+</sect2>
 
-</chapter>
+</sect1>
diff --git a/doc/src/sgml/indextypes.sgml b/doc/src/sgml/indextypes.sgml
new file mode 100644
index 0000000000..94a2b01afc
--- /dev/null
+++ b/doc/src/sgml/indextypes.sgml
@@ -0,0 +1,13 @@
+ <!-- doc/src/sgml/indextypes.sgml -->
+
+<chapter id="indextypes">
+<title>Built-in Index Access Methods</title>
+
+&btree;
+&gist;
+&spgist;
+&gin;
+&brin;
+&hash;
+
+</chapter>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 73b497bcf8..0235c0e352 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -257,12 +257,7 @@ break is not needed in a wider output rendering.
   &indexam;
   &generic-wal;
   &custom-rmgr;
-  &btree;
-  &gist;
-  &spgist;
-  &gin;
-  &brin;
-  &hash;
+  &indextypes;
   &storage;
   &transaction;
   &bki;
diff --git a/doc/src/sgml/spgist.sgml b/doc/src/sgml/spgist.sgml
index 102f8627bd..6af93719b8 100644
--- a/doc/src/sgml/spgist.sgml
+++ b/doc/src/sgml/spgist.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/spgist.sgml -->
 
-<chapter id="spgist">
+<sect1 id="spgist">
 <title>SP-GiST Indexes</title>
 
    <indexterm>
@@ -8,7 +8,7 @@
     <secondary>SP-GiST</secondary>
    </indexterm>
 
-<sect1 id="spgist-intro">
+<sect2 id="spgist-intro">
  <title>Introduction</title>
 
  <para>
@@ -51,9 +51,9 @@
   <ulink url="http://www.sai.msu.su/~megera/wiki/spgist_dev">web site</ulink>.
  </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="spgist-builtin-opclasses">
+<sect2 id="spgist-builtin-opclasses">
  <title>Built-in Operator Classes</title>
 
  <para>
@@ -191,9 +191,9 @@
   search over indexed point or polygon data sets.
  </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="spgist-extensibility">
+<sect2 id="spgist-extensibility">
  <title>Extensibility</title>
 
  <para>
@@ -933,9 +933,9 @@ LANGUAGE C STRICT;
    <function>PG_GET_COLLATION()</function> mechanism.
   </para>
 
-</sect1>
+</sect2>
 
-<sect1 id="spgist-implementation">
+<sect2 id="spgist-implementation">
  <title>Implementation</title>
 
   <para>
@@ -944,7 +944,7 @@ LANGUAGE C STRICT;
    know.
   </para>
 
- <sect2 id="spgist-limits">
+ <sect3 id="spgist-limits">
   <title>SP-GiST Limits</title>
 
   <para>
@@ -991,9 +991,9 @@ LANGUAGE C STRICT;
    leaf datum does not become any smaller within ten cycles
    of <function>choose</function> method calls.
   </para>
- </sect2>
+ </sect3>
 
- <sect2 id="spgist-null-labels">
+ <sect3 id="spgist-null-labels">
   <title>SP-GiST Without Node Labels</title>
 
   <para>
@@ -1018,9 +1018,9 @@ LANGUAGE C STRICT;
    for <function>choose</function> to return <literal>spgAddNode</literal>, since the set
    of nodes is supposed to be fixed in such cases.
   </para>
- </sect2>
+ </sect3>
 
- <sect2 id="spgist-all-the-same">
+ <sect3 id="spgist-all-the-same">
   <title><quote>All-the-Same</quote> Inner Tuples</title>
 
   <para>
@@ -1056,11 +1056,11 @@ LANGUAGE C STRICT;
    depending on how much the <function>inner_consistent</function> function normally
    assumes about the meaning of the nodes.
   </para>
- </sect2>
+ </sect3>
 
-</sect1>
+</sect2>
 
-<sect1 id="spgist-examples">
+<sect2 id="spgist-examples">
  <title>Examples</title>
 
  <para>
@@ -1071,6 +1071,6 @@ LANGUAGE C STRICT;
   and <filename>src/backend/utils/adt/</filename> to see the code.
  </para>
 
-</sect1>
+</sect2>
 
-</chapter>
+</sect1>
-- 
2.39.3 (Apple Git-145)



  [application/octet-stream] v2-0001-docs-Remove-the-Installation-from-Binaries-chapte.patch (4.2K, ../../CA+Tgmoaf2ziTh9Z36hdBA47VwoQa8GG_EmvdN8PN3eKygECTKQ@mail.gmail.com/5-v2-0001-docs-Remove-the-Installation-from-Binaries-chapte.patch)
  download | inline diff:
From 3a21aee199804b557631960e2eae6223ed93bd19 Mon Sep 17 00:00:00 2001
From: Robert Haas <[email protected]>
Date: Wed, 20 Mar 2024 10:08:05 -0400
Subject: [PATCH v2 1/5] docs: Remove the "Installation from Binaries" chapter.

The entire chapter was four sentences. Move the most useful
information from those sentences to the "Installation from Source
Code" chapter, and rename that to just "Installation".
---
 doc/src/sgml/filelist.sgml         |  1 -
 doc/src/sgml/install-binaries.sgml | 24 ------------------------
 doc/src/sgml/installation.sgml     | 23 +++++++++++++++++------
 doc/src/sgml/postgres.sgml         |  1 -
 4 files changed, 17 insertions(+), 32 deletions(-)
 delete mode 100644 doc/src/sgml/install-binaries.sgml

diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index e0dca81cb2..b7d1222e3e 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -36,7 +36,6 @@
 <!ENTITY client-auth   SYSTEM "client-auth.sgml">
 <!ENTITY diskusage     SYSTEM "diskusage.sgml">
 <!ENTITY high-availability      SYSTEM "high-availability.sgml">
-<!ENTITY installbin    SYSTEM "install-binaries.sgml">
 <!ENTITY installation  SYSTEM "installation.sgml">
 <!ENTITY targets-meson  SYSTEM "targets-meson.sgml">
 <!ENTITY maintenance   SYSTEM "maintenance.sgml">
diff --git a/doc/src/sgml/install-binaries.sgml b/doc/src/sgml/install-binaries.sgml
deleted file mode 100644
index 001c3c7be0..0000000000
--- a/doc/src/sgml/install-binaries.sgml
+++ /dev/null
@@ -1,24 +0,0 @@
-<!-- doc/src/sgml/install-binaries.sgml -->
-<chapter id="install-binaries">
- <title>Installation from Binaries</title>
-
- <indexterm>
-  <primary>installation</primary>
-  <secondary>binaries</secondary>
- </indexterm>
-
- <para>
-  <productname>PostgreSQL</productname> is available in the form of binary
-  packages for most common operating systems today. When available, this is
-  the recommended way to install PostgreSQL for users of the system. Building
-  from source (see <xref linkend="installation" />) is only recommended for
-  people developing <productname>PostgreSQL</productname> or extensions.
- </para>
-
- <para>
-  For an updated list of platforms providing binary packages, please visit
-  the download section on the <productname>PostgreSQL</productname> website at
-  <ulink url="https://www.postgresql.org/download/"></ulink> and follow the
-  instructions for the specific platform.
- </para>
-</chapter>
diff --git a/doc/src/sgml/installation.sgml b/doc/src/sgml/installation.sgml
index a453f804cd..7b2e6786f4 100644
--- a/doc/src/sgml/installation.sgml
+++ b/doc/src/sgml/installation.sgml
@@ -1,18 +1,29 @@
 <!-- doc/src/sgml/installation.sgml -->
 
 <chapter id="installation">
- <title>Installation from Source Code</title>
+ <title>Installation</title>
 
  <indexterm zone="installation">
   <primary>installation</primary>
  </indexterm>
 
  <para>
-  This chapter describes the installation of
-  <productname>PostgreSQL</productname> using the source code
-  distribution.  If you are installing a pre-packaged distribution,
-  such as an RPM or Debian package, ignore this chapter
-  and see <xref linkend="install-binaries" /> instead.
+  Since <productname>PostgreSQL</productname> is available in the form of
+  binary packages for most common operating systems today, it is typically not
+  necessary to build from source.
+ </para>
+
+ <para>
+  For an updated list of platforms providing binary packages, please visit
+  the download section on the <productname>PostgreSQL</productname> website at
+  <ulink url="https://www.postgresql.org/download/"></ulink> and follow the
+  instructions for the specific platform.
+ </para>
+
+ <para>
+  If you wish to compile from source code, for example to develop
+  <productname>PostgreSQL</productname> or an extension, the following
+  sections explain how to do this.
  </para>
 
  <sect1 id="install-requirements">
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 2c107199d3..7c234ff1db 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -150,7 +150,6 @@ break is not needed in a wider output rendering.
    </para>
   </partintro>
 
-  &installbin;
   &installation;
   &runtime;
   &config;
-- 
2.39.3 (Apple Git-145)



  [application/octet-stream] v2-0005-docs-Merge-all-procedural-language-documentation-.patch (43.5K, ../../CA+Tgmoaf2ziTh9Z36hdBA47VwoQa8GG_EmvdN8PN3eKygECTKQ@mail.gmail.com/6-v2-0005-docs-Merge-all-procedural-language-documentation-.patch)
  download | inline diff:
From 61e6f930d24d72b1212fafaed904205fa9ca15a0 Mon Sep 17 00:00:00 2001
From: Robert Haas <[email protected]>
Date: Thu, 21 Mar 2024 10:20:34 -0400
Subject: [PATCH v2 5/5] docs: Merge all procedural language documentation into
 one chapter.

The documentation index is getting very long, which makes it hard
to find things. These chapters are consecutive and cover closely related
topics, so merge them into one. Hopefully, that will reduce the size
of the index without making it harder for users to find the information
they need.

Rather than actually combining all of the SGML into a single file,
keep one file per <sect1>, and add a glue file that includes all
of them.
---
 doc/src/sgml/filelist.sgml |   1 +
 doc/src/sgml/plang.sgml    |  47 ++++++
 doc/src/sgml/plperl.sgml   |  52 +++----
 doc/src/sgml/plpgsql.sgml  | 300 ++++++++++++++++++-------------------
 doc/src/sgml/plpython.sgml |  80 +++++-----
 doc/src/sgml/pltcl.sgml    |  52 +++----
 doc/src/sgml/postgres.sgml |   8 +-
 doc/src/sgml/xplang.sgml   |  42 +-----
 8 files changed, 292 insertions(+), 290 deletions(-)
 create mode 100644 doc/src/sgml/plang.sgml

diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml
index 1bb662c16f..b801d1cdf3 100644
--- a/doc/src/sgml/filelist.sgml
+++ b/doc/src/sgml/filelist.sgml
@@ -66,6 +66,7 @@
 <!ENTITY xaggr      SYSTEM "xaggr.sgml">
 <!ENTITY xfunc      SYSTEM "xfunc.sgml">
 <!ENTITY xindex     SYSTEM "xindex.sgml">
+<!ENTITY plang      SYSTEM "plang.sgml">
 <!ENTITY xplang     SYSTEM "xplang.sgml">
 <!ENTITY xoper      SYSTEM "xoper.sgml">
 <!ENTITY xtypes     SYSTEM "xtypes.sgml">
diff --git a/doc/src/sgml/plang.sgml b/doc/src/sgml/plang.sgml
new file mode 100644
index 0000000000..cdcf81ca3d
--- /dev/null
+++ b/doc/src/sgml/plang.sgml
@@ -0,0 +1,47 @@
+<!-- doc/src/sgml/xplang.sgml -->
+
+ <chapter id="plang">
+  <title>Procedural Languages</title>
+
+  <indexterm zone="plang">
+   <primary>procedural language</primary>
+  </indexterm>
+
+  <para>
+   <productname>PostgreSQL</productname> allows user-defined functions
+   to be written in other languages besides SQL and C.  These other
+   languages are generically called <firstterm>procedural
+   languages</firstterm> (<acronym>PL</acronym>s).  For a function
+   written in a procedural language, the database server has
+   no built-in knowledge about how to interpret the function's source
+   text. Instead, the task is passed to a special handler that knows
+   the details of the language.  The handler could either do all the
+   work of parsing, syntax analysis, execution, etc. itself, or it
+   could serve as <quote>glue</quote> between
+   <productname>PostgreSQL</productname> and an existing implementation
+   of a programming language.  The handler itself is a
+   C language function compiled into a shared object and
+   loaded on demand, just like any other C function.
+  </para>
+
+  <para>
+   There are currently four procedural languages available in the
+   standard <productname>PostgreSQL</productname> distribution:
+   <application>PL/pgSQL</application> (<xref linkend="plpgsql"/>),
+   <application>PL/Tcl</application> (<xref linkend="pltcl"/>),
+   <application>PL/Perl</application> (<xref linkend="plperl"/>), and
+   <application>PL/Python</application> (<xref linkend="plpython"/>).
+   There are additional procedural languages available that are not
+   included in the core distribution. <xref linkend="external-projects"/>
+   has information about finding them. In addition other languages can
+   be defined by users; the basics of developing a new procedural
+   language are covered in <xref linkend="plhandler"/>.
+  </para>
+
+  &xplang;
+  &plsql;
+  &pltcl;
+  &plperl;
+  &plpython;
+
+</chapter>
diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml
index 25b1077ad7..912677724a 100644
--- a/doc/src/sgml/plperl.sgml
+++ b/doc/src/sgml/plperl.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/plperl.sgml -->
 
- <chapter id="plperl">
+ <sect1 id="plperl">
   <title>PL/Perl &mdash; Perl Procedural Language</title>
 
   <indexterm zone="plperl">
@@ -46,7 +46,7 @@
    </para>
   </note>
 
- <sect1 id="plperl-funcs">
+ <sect2 id="plperl-funcs">
   <title>PL/Perl Functions and Arguments</title>
 
   <para>
@@ -405,9 +405,9 @@ use strict;
   The <literal>feature</literal> pragma is also available to <function>use</function> if your Perl is version 5.10.0 or higher.
   </para>
 
- </sect1>
+ </sect2>
 
- <sect1 id="plperl-data">
+ <sect2 id="plperl-data">
   <title>Data Values in PL/Perl</title>
 
   <para>
@@ -425,12 +425,12 @@ use strict;
    for <type>bool</type> values.  Several examples of transform modules
    are included in the <productname>PostgreSQL</productname> distribution.
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plperl-builtins">
+ <sect2 id="plperl-builtins">
   <title>Built-in Functions</title>
 
- <sect2 id="plperl-database">
+ <sect3 id="plperl-database">
   <title>Database Access from PL/Perl</title>
 
   <para>
@@ -779,9 +779,9 @@ CALL transaction_test1();
      </listitem>
     </varlistentry>
    </variablelist>
- </sect2>
+ </sect3>
 
- <sect2 id="plperl-utility-functions">
+ <sect3 id="plperl-utility-functions">
   <title>Utility Functions in PL/Perl</title>
 
    <variablelist>
@@ -993,10 +993,10 @@ CALL transaction_test1();
     </varlistentry>
 
    </variablelist>
-  </sect2>
- </sect1>
+  </sect3>
+ </sect2>
 
- <sect1 id="plperl-global">
+ <sect2 id="plperl-global">
   <title>Global Values in PL/Perl</title>
 
   <para>
@@ -1069,9 +1069,9 @@ $$ LANGUAGE plperl;
    them <literal>SECURITY DEFINER</literal>.  You must of course take care that
    such functions can't be used to do anything unintended.
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plperl-trusted">
+ <sect2 id="plperl-trusted">
   <title>Trusted and Untrusted PL/Perl</title>
 
   <indexterm zone="plperl-trusted">
@@ -1169,9 +1169,9 @@ $$ LANGUAGE plperl;
    </para>
   </note>
 
- </sect1>
+ </sect2>
 
- <sect1 id="plperl-triggers">
+ <sect2 id="plperl-triggers">
   <title>PL/Perl Triggers</title>
 
   <para>
@@ -1357,9 +1357,9 @@ CREATE TRIGGER test_valid_id_trig
     FOR EACH ROW EXECUTE FUNCTION valid_id();
 </programlisting>
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plperl-event-triggers">
+ <sect2 id="plperl-event-triggers">
   <title>PL/Perl Event Triggers</title>
 
   <para>
@@ -1407,12 +1407,12 @@ CREATE EVENT TRIGGER perl_a_snitch
     EXECUTE FUNCTION perlsnitch();
 </programlisting>
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plperl-under-the-hood">
+ <sect2 id="plperl-under-the-hood">
   <title>PL/Perl Under the Hood</title>
 
- <sect2 id="plperl-config">
+ <sect3 id="plperl-config">
   <title>Configuration</title>
 
   <para>
@@ -1538,9 +1538,9 @@ DO 'elog(WARNING, join ", ", sort keys %INC)' LANGUAGE plperl;
      </varlistentry>
 
   </variablelist>
-</sect2>
+</sect3>
 
- <sect2 id="plperl-missing">
+ <sect3 id="plperl-missing">
   <title>Limitations and Missing Features</title>
 
   <para>
@@ -1588,8 +1588,8 @@ DO 'elog(WARNING, join ", ", sort keys %INC)' LANGUAGE plperl;
      </listitem>
    </itemizedlist>
   </para>
- </sect2>
+ </sect3>
 
- </sect1>
+ </sect2>
 
-</chapter>
+</sect1>
diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml
index 6f880b705f..4175e4763b 100644
--- a/doc/src/sgml/plpgsql.sgml
+++ b/doc/src/sgml/plpgsql.sgml
@@ -1,13 +1,13 @@
 <!-- doc/src/sgml/plpgsql.sgml -->
 
-<chapter id="plpgsql">
+<sect1 id="plpgsql">
   <title><application>PL/pgSQL</application> &mdash; <acronym>SQL</acronym> Procedural Language</title>
 
  <indexterm zone="plpgsql">
   <primary>PL/pgSQL</primary>
  </indexterm>
 
- <sect1 id="plpgsql-overview">
+ <sect2 id="plpgsql-overview">
   <title>Overview</title>
 
  <para>
@@ -65,7 +65,7 @@
     administrators could choose to remove it.
    </para>
 
-  <sect2 id="plpgsql-advantages">
+  <sect3 id="plpgsql-advantages">
    <title>Advantages of Using <application>PL/pgSQL</application></title>
 
     <para>
@@ -112,9 +112,9 @@
      Also, with <application>PL/pgSQL</application> you can use all
      the data types, operators and functions of SQL.
     </para>
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpgsql-args-results">
+  <sect3 id="plpgsql-args-results">
    <title>Supported Argument and Result Data Types</title>
 
     <para>
@@ -174,10 +174,10 @@
      <xref linkend="plpgsql-declaration-parameters"/> and
      <xref linkend="plpgsql-statements-returning"/>.
     </para>
-  </sect2>
- </sect1>
+  </sect3>
+ </sect2>
 
- <sect1 id="plpgsql-structure">
+ <sect2 id="plpgsql-structure">
   <title>Structure of <application>PL/pgSQL</application></title>
 
   <para>
@@ -310,9 +310,9 @@ $$ LANGUAGE plpgsql;
      outer transaction.  For more about that see <xref
      linkend="plpgsql-error-trapping"/>.
     </para>
-  </sect1>
+  </sect2>
 
-  <sect1 id="plpgsql-declarations">
+  <sect2 id="plpgsql-declarations">
     <title>Declarations</title>
 
     <para>
@@ -393,7 +393,7 @@ DECLARE
 </programlisting>
      </para>
 
-    <sect2 id="plpgsql-declaration-parameters">
+    <sect3 id="plpgsql-declaration-parameters">
      <title>Declaring Function Parameters</title>
 
      <para>
@@ -637,9 +637,9 @@ SELECT add_three_values(1, 2, 4.7);
       The function using <type>anyelement</type> would require you to
       cast the three inputs to the same type manually.
      </para>
-    </sect2>
+    </sect3>
 
-  <sect2 id="plpgsql-declaration-alias">
+  <sect3 id="plpgsql-declaration-alias">
    <title><literal>ALIAS</literal></title>
 
 <synopsis>
@@ -669,9 +669,9 @@ DECLARE
     object, unrestricted use can be confusing.  It's best to use it only
     for the purpose of overriding predetermined names.
    </para>
-   </sect2>
+   </sect3>
 
-  <sect2 id="plpgsql-declaration-type">
+  <sect3 id="plpgsql-declaration-type">
    <title>Copying Types</title>
 
 <synopsis>
@@ -724,9 +724,9 @@ user_ids users.user_id%TYPE ARRAY[4];  -- equivalent to the above
     arguments or result placeholders.
    </para>
 
-  </sect2>
+  </sect3>
 
-    <sect2 id="plpgsql-declaration-rowtypes">
+    <sect3 id="plpgsql-declaration-rowtypes">
      <title>Row Types</title>
 
 <synopsis>
@@ -787,9 +787,9 @@ $$ LANGUAGE plpgsql;
 SELECT merge_fields(t.*) FROM table1 t WHERE ... ;
 </programlisting>
    </para>
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpgsql-declaration-records">
+  <sect3 id="plpgsql-declaration-records">
    <title>Record Types</title>
 
 <synopsis>
@@ -817,9 +817,9 @@ SELECT merge_fields(t.*) FROM table1 t WHERE ... ;
     calling query is parsed, whereas a record variable can change its row
     structure on-the-fly.
    </para>
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpgsql-declaration-collation">
+  <sect3 id="plpgsql-declaration-collation">
    <title>Collation of <application>PL/pgSQL</application> Variables</title>
 
    <indexterm>
@@ -910,10 +910,10 @@ $$ LANGUAGE plpgsql;
     parameters, or local variables used in the expression, just as would
     happen in a plain SQL command.
    </para>
+  </sect3>
   </sect2>
-  </sect1>
 
-  <sect1 id="plpgsql-expressions">
+  <sect2 id="plpgsql-expressions">
   <title>Expressions</title>
 
     <para>
@@ -972,9 +972,9 @@ IF count(*) &gt; 0 FROM my_table THEN ...
      more than one row.  (If it produces no rows, the result is taken as
      NULL.)
     </para>
-  </sect1>
+  </sect2>
 
-  <sect1 id="plpgsql-statements">
+  <sect2 id="plpgsql-statements">
   <title>Basic Statements</title>
 
    <para>
@@ -986,7 +986,7 @@ IF count(*) &gt; 0 FROM my_table THEN ...
     as described in <xref linkend="plpgsql-statements-general-sql"/>.
    </para>
 
-   <sect2 id="plpgsql-statements-assignment">
+   <sect3 id="plpgsql-statements-assignment">
     <title>Assignment</title>
 
     <para>
@@ -1027,9 +1027,9 @@ my_array[1:3] := array[1,2,3];
 complex_array[n].realpart = 12.3;
 </programlisting>
     </para>
-   </sect2>
+   </sect3>
 
-   <sect2 id="plpgsql-statements-general-sql">
+   <sect3 id="plpgsql-statements-general-sql">
     <title>Executing SQL Commands</title>
 
     <para>
@@ -1146,9 +1146,9 @@ PERFORM <replaceable>query</replaceable>;
 PERFORM create_mv('cs_session_page_requests_mv', my_query);
 </programlisting>
     </para>
-   </sect2>
+   </sect3>
 
-   <sect2 id="plpgsql-statements-sql-onerow">
+   <sect3 id="plpgsql-statements-sql-onerow">
     <title>Executing a Command with a Single-Row Result</title>
 
     <indexterm zone="plpgsql-statements-sql-onerow">
@@ -1307,9 +1307,9 @@ CONTEXT:  PL/pgSQL function get_userid(text) line 6 at SQL statement
      </para>
     </note>
 
-   </sect2>
+   </sect3>
 
-   <sect2 id="plpgsql-statements-executing-dyn">
+   <sect3 id="plpgsql-statements-executing-dyn">
     <title>Executing Dynamic Commands</title>
 
     <para>
@@ -1608,9 +1608,9 @@ EXECUTE format('UPDATE tbl SET %I = $1 WHERE key = $2', colname)
      linkend="plpgsql-porting-ex2"/>, which builds and executes a
      <command>CREATE FUNCTION</command> command to define a new function.
     </para>
-   </sect2>
+   </sect3>
 
-   <sect2 id="plpgsql-statements-diagnostics">
+   <sect3 id="plpgsql-statements-diagnostics">
     <title>Obtaining the Result Status</title>
 
     <para>
@@ -1749,9 +1749,9 @@ GET DIAGNOSTICS integer_var = ROW_COUNT;
      affect only the current function.
     </para>
 
-   </sect2>
+   </sect3>
 
-   <sect2 id="plpgsql-statements-null">
+   <sect3 id="plpgsql-statements-null">
     <title>Doing Nothing At All</title>
 
     <para>
@@ -1795,10 +1795,10 @@ END;
      </para>
     </note>
 
-   </sect2>
-  </sect1>
+   </sect3>
+  </sect2>
 
-  <sect1 id="plpgsql-control-structures">
+  <sect2 id="plpgsql-control-structures">
    <title>Control Structures</title>
 
    <para>
@@ -1809,7 +1809,7 @@ END;
     flexible and powerful way.
    </para>
 
-   <sect2 id="plpgsql-statements-returning">
+   <sect3 id="plpgsql-statements-returning">
     <title>Returning from a Function</title>
 
     <para>
@@ -1818,7 +1818,7 @@ END;
      NEXT</command>.
     </para>
 
-    <sect3 id="plpgsql-statements-returning-return">
+    <sect4 id="plpgsql-statements-returning-return">
      <title><command>RETURN</command></title>
 
 <synopsis>
@@ -1877,9 +1877,9 @@ RETURN composite_type_var;
 RETURN (1, 2, 'three'::text);  -- must cast columns to correct types
 </programlisting>
      </para>
-    </sect3>
+    </sect4>
 
-    <sect3 id="plpgsql-statements-returning-return-next">
+    <sect4 id="plpgsql-statements-returning-return-next">
      <title><command>RETURN NEXT</command> and <command>RETURN QUERY</command></title>
     <indexterm>
      <primary>RETURN NEXT</primary>
@@ -2026,10 +2026,10 @@ SELECT * FROM get_available_flightid(CURRENT_DATE);
        increasing this parameter.
       </para>
      </note>
-    </sect3>
-   </sect2>
+    </sect4>
+   </sect3>
 
-   <sect2 id="plpgsql-statements-returning-procedure">
+   <sect3 id="plpgsql-statements-returning-procedure">
     <title>Returning from a Procedure</title>
 
     <para>
@@ -2043,9 +2043,9 @@ SELECT * FROM get_available_flightid(CURRENT_DATE);
      If the procedure has output parameters, the final values of the output
      parameter variables will be returned to the caller.
     </para>
-   </sect2>
+   </sect3>
 
-   <sect2 id="plpgsql-statements-calling-procedure">
+   <sect3 id="plpgsql-statements-calling-procedure">
     <title>Calling a Procedure</title>
 
     <para>
@@ -2079,9 +2079,9 @@ $$;
      variable or a field of a composite-type variable.  Currently,
      it cannot be an element of an array.
     </para>
-   </sect2>
+   </sect3>
 
-   <sect2 id="plpgsql-conditionals">
+   <sect3 id="plpgsql-conditionals">
     <title>Conditionals</title>
 
     <para>
@@ -2111,7 +2111,7 @@ $$;
     </itemizedlist>
     </para>
 
-    <sect3 id="plpgsql-conditionals-if-then">
+    <sect4 id="plpgsql-conditionals-if-then">
      <title><literal>IF-THEN</literal></title>
 
 <synopsis>
@@ -2136,9 +2136,9 @@ IF v_user_id &lt;&gt; 0 THEN
 END IF;
 </programlisting>
        </para>
-     </sect3>
+     </sect4>
 
-     <sect3 id="plpgsql-conditionals-if-then-else">
+     <sect4 id="plpgsql-conditionals-if-then-else">
       <title><literal>IF-THEN-ELSE</literal></title>
 
 <synopsis>
@@ -2177,9 +2177,9 @@ ELSE
 END IF;
 </programlisting>
      </para>
-    </sect3>
+    </sect4>
 
-     <sect3 id="plpgsql-conditionals-if-then-elsif">
+     <sect4 id="plpgsql-conditionals-if-then-elsif">
       <title><literal>IF-THEN-ELSIF</literal></title>
 
 <synopsis>
@@ -2253,9 +2253,9 @@ END IF;
         for each <literal>IF</literal>, so it is much more cumbersome than
         using <literal>ELSIF</literal> when there are many alternatives.
        </para>
-     </sect3>
+     </sect4>
 
-     <sect3 id="plpgsql-conditionals-simple-case">
+     <sect4 id="plpgsql-conditionals-simple-case">
       <title>Simple <literal>CASE</literal></title>
 
 <synopsis>
@@ -2296,9 +2296,9 @@ CASE x
 END CASE;
 </programlisting>
       </para>
-     </sect3>
+     </sect4>
 
-     <sect3 id="plpgsql-conditionals-searched-case">
+     <sect4 id="plpgsql-conditionals-searched-case">
       <title>Searched <literal>CASE</literal></title>
 
 <synopsis>
@@ -2347,10 +2347,10 @@ END CASE;
        than doing nothing.
       </para>
 
-     </sect3>
-   </sect2>
+     </sect4>
+   </sect3>
 
-   <sect2 id="plpgsql-control-structures-loops">
+   <sect3 id="plpgsql-control-structures-loops">
     <title>Simple Loops</title>
 
     <indexterm zone="plpgsql-control-structures-loops">
@@ -2365,7 +2365,7 @@ END CASE;
      <application>PL/pgSQL</application> function to repeat a series of commands.
     </para>
 
-    <sect3 id="plpgsql-control-structures-loops-loop">
+    <sect4 id="plpgsql-control-structures-loops-loop">
      <title><literal>LOOP</literal></title>
 
 <synopsis>
@@ -2383,9 +2383,9 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>;
       and <literal>CONTINUE</literal> statements within nested loops to
       specify which loop those statements refer to.
      </para>
-    </sect3>
+    </sect4>
 
-     <sect3 id="plpgsql-control-structures-loops-exit">
+     <sect4 id="plpgsql-control-structures-loops-exit">
       <title><literal>EXIT</literal></title>
 
      <indexterm>
@@ -2455,9 +2455,9 @@ BEGIN
 END;
 </programlisting>
        </para>
-     </sect3>
+     </sect4>
 
-     <sect3 id="plpgsql-control-structures-loops-continue">
+     <sect4 id="plpgsql-control-structures-loops-continue">
       <title><literal>CONTINUE</literal></title>
 
      <indexterm>
@@ -2503,10 +2503,10 @@ LOOP
 END LOOP;
 </programlisting>
        </para>
-     </sect3>
+     </sect4>
 
 
-     <sect3 id="plpgsql-control-structures-loops-while">
+     <sect4 id="plpgsql-control-structures-loops-while">
       <title><literal>WHILE</literal></title>
 
      <indexterm>
@@ -2541,9 +2541,9 @@ WHILE NOT done LOOP
 END LOOP;
 </programlisting>
        </para>
-     </sect3>
+     </sect4>
 
-     <sect3 id="plpgsql-integer-for">
+     <sect4 id="plpgsql-integer-for">
       <title><literal>FOR</literal> (Integer Variant)</title>
 
 <synopsis>
@@ -2597,10 +2597,10 @@ END LOOP;
         referenced with a qualified name, using that
         <replaceable>label</replaceable>.
        </para>
-     </sect3>
-   </sect2>
+     </sect4>
+   </sect3>
 
-   <sect2 id="plpgsql-records-iterating">
+   <sect3 id="plpgsql-records-iterating">
     <title>Looping through Query Results</title>
 
     <para>
@@ -2694,9 +2694,9 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>;
      through is to declare it as a cursor.  This is described in
      <xref linkend="plpgsql-cursor-for-loop"/>.
     </para>
-   </sect2>
+   </sect3>
 
-   <sect2 id="plpgsql-foreach-array">
+   <sect3 id="plpgsql-foreach-array">
     <title>Looping through Arrays</title>
 
     <para>
@@ -2778,9 +2778,9 @@ NOTICE:  row = {7,8,9}
 NOTICE:  row = {10,11,12}
 </programlisting>
     </para>
-   </sect2>
+   </sect3>
 
-   <sect2 id="plpgsql-error-trapping">
+   <sect3 id="plpgsql-error-trapping">
     <title>Trapping Errors</title>
 
     <indexterm>
@@ -2943,7 +2943,7 @@ SELECT merge_db(1, 'dennis');
     </para>
     </example>
 
-   <sect3 id="plpgsql-exception-diagnostics">
+   <sect4 id="plpgsql-exception-diagnostics">
     <title>Obtaining Information about an Error</title>
 
     <para>
@@ -3069,10 +3069,10 @@ EXCEPTION WHEN OTHERS THEN
 END;
 </programlisting>
     </para>
-   </sect3>
-  </sect2>
+   </sect4>
+  </sect3>
 
-  <sect2 id="plpgsql-call-stack">
+  <sect3 id="plpgsql-call-stack">
    <title>Obtaining Execution Location Information</title>
 
    <para>
@@ -3124,10 +3124,10 @@ CONTEXT:  PL/pgSQL function outer_func() line 3 at RETURN
     returns the same sort of stack trace, but describing the location
     at which an error was detected, rather than the current location.
    </para>
+  </sect3>
   </sect2>
-  </sect1>
 
-  <sect1 id="plpgsql-cursors">
+  <sect2 id="plpgsql-cursors">
    <title>Cursors</title>
 
    <indexterm zone="plpgsql-cursors">
@@ -3148,7 +3148,7 @@ CONTEXT:  PL/pgSQL function outer_func() line 3 at RETURN
     large row sets from functions.
    </para>
 
-   <sect2 id="plpgsql-cursor-declarations">
+   <sect3 id="plpgsql-cursor-declarations">
     <title>Declaring Cursor Variables</title>
 
     <para>
@@ -3200,9 +3200,9 @@ DECLARE
      assumes that re-reading the query's output will give consistent
      results, which a volatile function might not do.
     </para>
-   </sect2>
+   </sect3>
 
-   <sect2 id="plpgsql-cursor-opening">
+   <sect3 id="plpgsql-cursor-opening">
     <title>Opening Cursors</title>
 
     <para>
@@ -3242,7 +3242,7 @@ DECLARE
      <xref linkend="plpgsql-cursor-returning"/>.
     </para>
 
-    <sect3 id="plpgsql-cursor-opening-open-for-query">
+    <sect4 id="plpgsql-cursor-opening-open-for-query">
      <title><command>OPEN FOR</command> <replaceable>query</replaceable></title>
 
 <synopsis>
@@ -3274,9 +3274,9 @@ OPEN <replaceable>unbound_cursorvar</replaceable> <optional> <optional> NO </opt
 OPEN curs1 FOR SELECT * FROM foo WHERE key = mykey;
 </programlisting>
        </para>
-     </sect3>
+     </sect4>
 
-    <sect3 id="plpgsql-cursor-opening-open-for-execute">
+    <sect4 id="plpgsql-cursor-opening-open-for-execute">
      <title><command>OPEN FOR EXECUTE</command></title>
 
 <synopsis>
@@ -3311,9 +3311,9 @@ OPEN curs1 FOR EXECUTE format('SELECT * FROM %I WHERE col1 = $1',tabname) USING
         is inserted via a <literal>USING</literal> parameter, so it needs
         no quoting.
        </para>
-     </sect3>
+     </sect4>
 
-    <sect3 id="plpgsql-open-bound-cursor">
+    <sect4 id="plpgsql-open-bound-cursor">
      <title>Opening a Bound Cursor</title>
 
 <synopsis>
@@ -3374,10 +3374,10 @@ BEGIN
     OPEN curs4;
 </programlisting>
          </para>
-     </sect3>
-   </sect2>
+     </sect4>
+   </sect3>
 
-   <sect2 id="plpgsql-cursor-using">
+   <sect3 id="plpgsql-cursor-using">
     <title>Using Cursors</title>
 
     <para>
@@ -3401,7 +3401,7 @@ BEGIN
      only until the end of the transaction.
     </para>
 
-    <sect3 id="plpgsql-cursor-using-fetch">
+    <sect4 id="plpgsql-cursor-using-fetch">
      <title><literal>FETCH</literal></title>
 
 <synopsis>
@@ -3456,9 +3456,9 @@ FETCH LAST FROM curs3 INTO x, y;
 FETCH RELATIVE -2 FROM curs4 INTO x;
 </programlisting>
        </para>
-     </sect3>
+     </sect4>
 
-    <sect3 id="plpgsql-cursor-using-move">
+    <sect4 id="plpgsql-cursor-using-move">
      <title><literal>MOVE</literal></title>
 
 <synopsis>
@@ -3483,9 +3483,9 @@ MOVE RELATIVE -2 FROM curs4;
 MOVE FORWARD 2 FROM curs4;
 </programlisting>
        </para>
-     </sect3>
+     </sect4>
 
-    <sect3 id="plpgsql-cursor-using-update-delete">
+    <sect4 id="plpgsql-cursor-using-update-delete">
      <title><literal>UPDATE/DELETE WHERE CURRENT OF</literal></title>
 
 <synopsis>
@@ -3509,9 +3509,9 @@ DELETE FROM <replaceable>table</replaceable> WHERE CURRENT OF <replaceable>curso
 UPDATE foo SET dataval = myval WHERE CURRENT OF curs1;
 </programlisting>
        </para>
-     </sect3>
+     </sect4>
 
-    <sect3 id="plpgsql-cursor-using-close">
+    <sect4 id="plpgsql-cursor-using-close">
      <title><literal>CLOSE</literal></title>
 
 <synopsis>
@@ -3530,9 +3530,9 @@ CLOSE <replaceable>cursor</replaceable>;
 CLOSE curs1;
 </programlisting>
        </para>
-     </sect3>
+     </sect4>
 
-    <sect3 id="plpgsql-cursor-returning">
+    <sect4 id="plpgsql-cursor-returning">
      <title>Returning Cursors</title>
 
        <para>
@@ -3643,10 +3643,10 @@ FETCH ALL FROM b;
 COMMIT;
 </programlisting>
        </para>
-     </sect3>
-   </sect2>
+     </sect4>
+   </sect3>
 
-   <sect2 id="plpgsql-cursor-for-loop">
+   <sect3 id="plpgsql-cursor-for-loop">
     <title>Looping through a Cursor's Result</title>
 
     <para>
@@ -3677,11 +3677,11 @@ END LOOP <optional> <replaceable>label</replaceable> </optional>;
      Each row returned by the cursor is successively assigned to this
      record variable and the loop body is executed.
     </para>
-   </sect2>
+   </sect3>
 
-  </sect1>
+  </sect2>
 
-  <sect1 id="plpgsql-transactions">
+  <sect2 id="plpgsql-transactions">
    <title>Transaction Management</title>
 
    <para>
@@ -3782,12 +3782,12 @@ CALL transaction_test2();
    <para>
     A transaction cannot be ended inside a block with exception handlers.
    </para>
-  </sect1>
+  </sect2>
 
-  <sect1 id="plpgsql-errors-and-messages">
+  <sect2 id="plpgsql-errors-and-messages">
    <title>Errors and Messages</title>
 
-  <sect2 id="plpgsql-statements-raise">
+  <sect3 id="plpgsql-statements-raise">
    <title>Reporting Errors and Messages</title>
 
    <indexterm>
@@ -3984,9 +3984,9 @@ RAISE unique_violation USING MESSAGE = 'Duplicate user ID: ' || user_id;
     </para>
    </note>
 
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpgsql-statements-assert">
+  <sect3 id="plpgsql-statements-assert">
    <title>Checking Assertions</title>
 
    <indexterm>
@@ -4043,11 +4043,11 @@ ASSERT <replaceable class="parameter">condition</replaceable> <optional> , <repl
     the <command>RAISE</command> statement, described above, for that.
    </para>
 
-  </sect2>
+  </sect3>
 
- </sect1>
+ </sect2>
 
- <sect1 id="plpgsql-trigger">
+ <sect2 id="plpgsql-trigger">
   <title>Trigger Functions</title>
 
   <indexterm zone="plpgsql-trigger">
@@ -4066,7 +4066,7 @@ ASSERT <replaceable class="parameter">condition</replaceable> <optional> , <repl
    automatically defined to describe the condition that triggered the call.
   </para>
 
-  <sect2 id="plpgsql-dml-trigger">
+  <sect3 id="plpgsql-dml-trigger">
    <title>Triggers on Data Changes</title>
 
   <para>
@@ -4680,9 +4680,9 @@ CREATE TRIGGER emp_audit_del
 </programlisting>
    </example>
 
-</sect2>
+</sect3>
 
-  <sect2 id="plpgsql-event-trigger">
+  <sect3 id="plpgsql-event-trigger">
    <title>Triggers on Events</title>
 
    <para>
@@ -4742,11 +4742,11 @@ $$ LANGUAGE plpgsql;
 CREATE EVENT TRIGGER snitch ON ddl_command_start EXECUTE FUNCTION snitch();
 </programlisting>
    </example>
-  </sect2>
+  </sect3>
 
-  </sect1>
+  </sect2>
 
-  <sect1 id="plpgsql-implementation">
+  <sect2 id="plpgsql-implementation">
    <title><application>PL/pgSQL</application> under the Hood</title>
 
    <para>
@@ -4754,7 +4754,7 @@ CREATE EVENT TRIGGER snitch ON ddl_command_start EXECUTE FUNCTION snitch();
     frequently important for <application>PL/pgSQL</application> users to know.
    </para>
 
-  <sect2 id="plpgsql-var-subst">
+  <sect3 id="plpgsql-var-subst">
    <title>Variable Substitution</title>
 
    <para>
@@ -4930,9 +4930,9 @@ $$ LANGUAGE plpgsql;
     the utility statement as a string and <command>EXECUTE</command> it.
    </para>
 
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpgsql-plan-caching">
+  <sect3 id="plpgsql-plan-caching">
    <title>Plan Caching</title>
 
    <para>
@@ -5083,11 +5083,11 @@ $$ LANGUAGE plpgsql;
      use of the <literal>now()</literal> function would still be a better idea.
     </para>
 
-  </sect2>
+  </sect3>
 
-  </sect1>
+  </sect2>
 
- <sect1 id="plpgsql-development-tips">
+ <sect2 id="plpgsql-development-tips">
   <title>Tips for Developing in <application>PL/pgSQL</application></title>
 
    <para>
@@ -5124,7 +5124,7 @@ $$ LANGUAGE plpgsql;
     making it easier to recreate and debug functions.
    </para>
 
-  <sect2 id="plpgsql-quote-tips">
+  <sect3 id="plpgsql-quote-tips">
    <title>Handling of Quotation Marks</title>
 
    <para>
@@ -5279,8 +5279,8 @@ a_output := a_output || $$ if v_$$ || referrer_keys.kind || $$ like '$$
    </varlistentry>
   </variablelist>
 
-  </sect2>
-  <sect2 id="plpgsql-extra-checks">
+  </sect3>
+  <sect3 id="plpgsql-extra-checks">
    <title>Additional Compile-Time and Run-Time Checks</title>
 
    <para>
@@ -5400,12 +5400,12 @@ HINT:  Make sure the query returns the exact list of columns.
 (1 row)
 </programlisting>
    </para>
-  </sect2>
- </sect1>
+  </sect3>
+ </sect2>
 
   <!-- **** Porting from Oracle PL/SQL **** -->
 
- <sect1 id="plpgsql-porting">
+ <sect2 id="plpgsql-porting">
   <title>Porting from <productname>Oracle</productname> PL/SQL</title>
 
   <indexterm zone="plpgsql-porting">
@@ -5519,7 +5519,7 @@ HINT:  Make sure the query returns the exact list of columns.
     </itemizedlist>
    </para>
 
-  <sect2 id="plpgsql-porting-examples">
+  <sect3 id="plpgsql-porting-examples">
    <title>Porting Examples</title>
 
    <para>
@@ -5912,9 +5912,9 @@ $$ LANGUAGE plpgsql;
     </calloutlist>
    </para>
    </example>
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpgsql-porting-other">
+  <sect3 id="plpgsql-porting-other">
    <title>Other Things to Watch For</title>
 
    <para>
@@ -5923,7 +5923,7 @@ $$ LANGUAGE plpgsql;
     <productname>PostgreSQL</productname>.
    </para>
 
-   <sect3 id="plpgsql-porting-exceptions">
+   <sect4 id="plpgsql-porting-exceptions">
     <title>Implicit Rollback after Exceptions</title>
 
     <para>
@@ -5953,9 +5953,9 @@ END;
      <command>SAVEPOINT</command> and <command>ROLLBACK TO</command> in a different way
      then some actual thought will be required.
     </para>
-   </sect3>
+   </sect4>
 
-   <sect3 id="plpgsql-porting-other-execute">
+   <sect4 id="plpgsql-porting-other-execute">
     <title><command>EXECUTE</command></title>
 
     <para>
@@ -5968,9 +5968,9 @@ END;
      type <literal>EXECUTE 'SELECT * FROM $1';</literal> will not work
      reliably unless you use these functions.
     </para>
-   </sect3>
+   </sect4>
 
-   <sect3 id="plpgsql-porting-optimization">
+   <sect4 id="plpgsql-porting-optimization">
     <title>Optimizing <application>PL/pgSQL</application> Functions</title>
 
     <para>
@@ -5994,10 +5994,10 @@ CREATE FUNCTION foo(...) RETURNS integer AS $$
 $$ LANGUAGE plpgsql STRICT IMMUTABLE;
 </programlisting>
     </para>
-   </sect3>
-  </sect2>
+   </sect4>
+  </sect3>
 
-  <sect2 id="plpgsql-porting-appendix">
+  <sect3 id="plpgsql-porting-appendix">
    <title>Appendix</title>
 
    <para>
@@ -6126,8 +6126,8 @@ END;
 $$ LANGUAGE plpgsql STRICT IMMUTABLE;
 ]]>
 </programlisting>
-  </sect2>
+  </sect3>
 
- </sect1>
+ </sect2>
 
-</chapter>
+</sect1>
diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml
index e5d51d6e9f..aaedb30d2e 100644
--- a/doc/src/sgml/plpython.sgml
+++ b/doc/src/sgml/plpython.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/plpython.sgml -->
 
-<chapter id="plpython">
+<sect1 id="plpython">
  <title>PL/Python &mdash; Python Procedural Language</title>
 
  <indexterm zone="plpython"><primary>PL/Python</primary></indexterm>
@@ -46,7 +46,7 @@
   </para>
  </note>
 
- <sect1 id="plpython-funcs">
+ <sect2 id="plpython-funcs">
   <title>PL/Python Functions</title>
 
   <para>
@@ -142,9 +142,9 @@ $$ LANGUAGE plpython3u;
    PL/Python.  It is better to treat the function parameters as
    read-only.
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plpython-data">
+ <sect2 id="plpython-data">
   <title>Data Values</title>
   <para>
    Generally speaking, the aim of PL/Python is to provide
@@ -153,7 +153,7 @@ $$ LANGUAGE plpython3u;
    below.
   </para>
 
-  <sect2 id="plpython-data-type-mapping">
+  <sect3 id="plpython-data-type-mapping">
    <title>Data Type Mapping</title>
    <para>
     When a PL/Python function is called, its arguments are converted from
@@ -267,9 +267,9 @@ $$ LANGUAGE plpython3u;
     return type and the Python data type of the actual return object
     are not flagged; the value will be converted in any case.
    </para>
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpython-data-null">
+  <sect3 id="plpython-data-null">
    <title>Null, None</title>
   <para>
    If an SQL null value<indexterm><primary>null value</primary><secondary
@@ -299,9 +299,9 @@ $$ LANGUAGE plpython3u;
    function, return the value <symbol>None</symbol>. This can be done whether the
    function is strict or not.
   </para>
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpython-arrays">
+  <sect3 id="plpython-arrays">
    <title>Arrays, Lists</title>
   <para>
    SQL array values are passed into PL/Python as a Python list.  To
@@ -367,9 +367,9 @@ SELECT return_str_arr();
 (1 row)
 </programlisting>
   </para>
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpython-data-composite-types">
+  <sect3 id="plpython-data-composite-types">
    <title>Composite Types</title>
   <para>
    Composite-type arguments are passed to the function as Python mappings. The
@@ -514,9 +514,9 @@ $$ LANGUAGE plpython3u;
 CALL python_triple(5, 10);
 </programlisting>
    </para>
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpython-data-set-returning-funcs">
+  <sect3 id="plpython-data-set-returning-funcs">
    <title>Set-Returning Functions</title>
   <para>
    A <application>PL/Python</application> function can also return sets of
@@ -613,10 +613,10 @@ $$ LANGUAGE plpython3u;
 SELECT * FROM multiout_simple_setof(3);
 </programlisting>
    </para>
-  </sect2>
- </sect1>
+  </sect3>
+ </sect2>
 
- <sect1 id="plpython-sharing">
+ <sect2 id="plpython-sharing">
   <title>Sharing Data</title>
   <para>
    The global dictionary <varname>SD</varname> is available to store
@@ -634,9 +634,9 @@ SELECT * FROM multiout_simple_setof(3);
    <function>myfunc2</function>.  The exception is the data in the
    <varname>GD</varname> dictionary, as mentioned above.
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plpython-do">
+ <sect2 id="plpython-do">
   <title>Anonymous Code Blocks</title>
 
   <para>
@@ -652,9 +652,9 @@ $$ LANGUAGE plpython3u;
    An anonymous code block receives no arguments, and whatever value it
    might return is discarded.  Otherwise it behaves just like a function.
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plpython-trigger">
+ <sect2 id="plpython-trigger">
   <title>Trigger Functions</title>
 
   <indexterm zone="plpython-trigger">
@@ -767,9 +767,9 @@ $$ LANGUAGE plpython3u;
    <literal>"MODIFY"</literal> to indicate you've modified the new row.
    Otherwise the return value is ignored.
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plpython-database">
+ <sect2 id="plpython-database">
   <title>Database Access</title>
 
   <para>
@@ -779,7 +779,7 @@ $$ LANGUAGE plpython3u;
    <literal>plpy.<replaceable>foo</replaceable></literal>.
   </para>
 
-  <sect2 id="plpython-database-access-funcs">
+  <sect3 id="plpython-database-access-funcs">
     <title>Database Access Functions</title>
 
   <para>
@@ -1037,9 +1037,9 @@ $$ LANGUAGE plpython3u;
    </varlistentry>
   </variablelist>
 
-  </sect2>
+  </sect3>
 
-  <sect2 id="plpython-trapping">
+  <sect3 id="plpython-trapping">
    <title>Trapping Errors</title>
 
    <para>
@@ -1109,10 +1109,10 @@ $$ LANGUAGE plpython3u;
     the <quote>SQLSTATE</quote> error code.  This approach provides
     approximately the same functionality
    </para>
-  </sect2>
- </sect1>
+  </sect3>
+ </sect2>
 
- <sect1 id="plpython-subtransaction">
+ <sect2 id="plpython-subtransaction">
   <title>Explicit Subtransactions</title>
 
   <para>
@@ -1124,7 +1124,7 @@ $$ LANGUAGE plpython3u;
    the form of explicit subtransactions.
   </para>
 
-  <sect2 id="plpython-subtransaction-context-managers">
+  <sect3 id="plpython-subtransaction-context-managers">
    <title>Subtransaction Context Managers</title>
 
    <para>
@@ -1189,10 +1189,10 @@ $$ LANGUAGE plpython3u;
     explicit subtransaction block would also cause the subtransaction
     to be rolled back.
    </para>
-  </sect2>
- </sect1>
+  </sect3>
+ </sect2>
 
- <sect1 id="plpython-transactions">
+ <sect2 id="plpython-transactions">
   <title>Transaction Management</title>
 
   <para>
@@ -1229,9 +1229,9 @@ CALL transaction_test1();
   <para>
    Transactions cannot be ended when an explicit subtransaction is active.
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plpython-util">
+ <sect2 id="plpython-util">
   <title>Utility Functions</title>
   <para>
    The <literal>plpy</literal> module also provides the functions
@@ -1317,9 +1317,9 @@ plpy.execute("UPDATE tbl SET %s = %s WHERE key = %s" % (
     plpy.quote_literal(keyvalue)))
 </programlisting>
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plpython-python23">
+ <sect2 id="plpython-python23">
   <title>Python 2 vs. Python 3</title>
 
   <para>
@@ -1328,9 +1328,9 @@ plpy.execute("UPDATE tbl SET %s = %s WHERE key = %s" % (
    <literal>plpythonu</literal> and <literal>plpython2u</literal> language
    names.
   </para>
- </sect1>
+ </sect2>
 
- <sect1 id="plpython-envar">
+ <sect2 id="plpython-envar">
   <title>Environment Variables</title>
 
   <para>
@@ -1393,5 +1393,5 @@ plpy.execute("UPDATE tbl SET %s = %s WHERE key = %s" % (
    the <command>python</command> man page are only effective in a
    command-line interpreter and not an embedded Python interpreter.)
   </para>
- </sect1>
-</chapter>
+ </sect2>
+</sect1>
diff --git a/doc/src/sgml/pltcl.sgml b/doc/src/sgml/pltcl.sgml
index b31f2c1330..9e12df3816 100644
--- a/doc/src/sgml/pltcl.sgml
+++ b/doc/src/sgml/pltcl.sgml
@@ -1,6 +1,6 @@
 <!-- doc/src/sgml/pltcl.sgml -->
 
- <chapter id="pltcl">
+ <sect1 id="pltcl">
   <title>PL/Tcl &mdash; Tcl Procedural Language</title>
 
   <indexterm zone="pltcl">
@@ -21,7 +21,7 @@
 
   <!-- **** PL/Tcl overview **** -->
 
-  <sect1 id="pltcl-overview">
+  <sect2 id="pltcl-overview">
    <title>Overview</title>
 
    <para>
@@ -70,11 +70,11 @@
     <literal>CREATE EXTENSION pltcl</literal> or
     <literal>CREATE EXTENSION pltclu</literal>.
    </para>
-  </sect1>
+  </sect2>
 
   <!-- **** PL/Tcl description **** -->
 
-   <sect1 id="pltcl-functions">
+   <sect2 id="pltcl-functions">
     <title>PL/Tcl Functions and Arguments</title>
 
     <para>
@@ -238,9 +238,9 @@ $$ LANGUAGE pltcl;
 </programlisting>
     </para>
 
-   </sect1>
+   </sect2>
 
-   <sect1 id="pltcl-data">
+   <sect2 id="pltcl-data">
     <title>Data Values in PL/Tcl</title>
 
     <para>
@@ -252,9 +252,9 @@ $$ LANGUAGE pltcl;
      result type, or for the specified column of a composite result type.
     </para>
 
-   </sect1>
+   </sect2>
 
-   <sect1 id="pltcl-global">
+   <sect2 id="pltcl-global">
     <title>Global Data in PL/Tcl</title>
 
     <indexterm zone="pltcl-global">
@@ -314,9 +314,9 @@ $$ LANGUAGE pltcl;
      An example of using <literal>GD</literal> appears in the
      <function>spi_execp</function> example below.
     </para>
-   </sect1>
+   </sect2>
 
-   <sect1 id="pltcl-dbaccess">
+   <sect2 id="pltcl-dbaccess">
     <title>Database Access from PL/Tcl</title>
 
     <para>
@@ -570,9 +570,9 @@ SELECT 'doesn''t' AS ret
     </variablelist>
     </para>
 
-   </sect1>
+   </sect2>
 
-   <sect1 id="pltcl-trigger">
+   <sect2 id="pltcl-trigger">
     <title>Trigger Functions in PL/Tcl</title>
 
     <indexterm>
@@ -782,9 +782,9 @@ CREATE TRIGGER trig_mytab_modcount BEFORE INSERT OR UPDATE ON mytab
      name; that's supplied from the trigger arguments.  This lets the
      trigger function be reused with different tables.
     </para>
-   </sect1>
+   </sect2>
 
-   <sect1 id="pltcl-event-trigger">
+   <sect2 id="pltcl-event-trigger">
     <title>Event Trigger Functions in PL/Tcl</title>
 
     <indexterm>
@@ -841,9 +841,9 @@ $$ LANGUAGE pltcl;
 CREATE EVENT TRIGGER tcl_a_snitch ON ddl_command_start EXECUTE FUNCTION tclsnitch();
 </programlisting>
     </para>
-   </sect1>
+   </sect2>
 
-   <sect1 id="pltcl-error-handling">
+   <sect2 id="pltcl-error-handling">
     <title>Error Handling in PL/Tcl</title>
 
     <indexterm>
@@ -916,9 +916,9 @@ if {[catch { spi_exec $sql_command }]} {
      (The double colons explicitly specify that <varname>errorCode</varname>
      is a global variable.)
     </para>
-   </sect1>
+   </sect2>
 
-   <sect1 id="pltcl-subtransactions">
+   <sect2 id="pltcl-subtransactions">
     <title>Explicit Subtransactions in PL/Tcl</title>
 
     <indexterm>
@@ -998,9 +998,9 @@ $$ LANGUAGE pltcl;
      contained Tcl code (for instance, due to <function>return</function>) do
      not cause a rollback.
     </para>
-   </sect1>
+   </sect2>
 
-   <sect1 id="pltcl-transactions">
+   <sect2 id="pltcl-transactions">
     <title>Transaction Management</title>
 
     <para>
@@ -1039,9 +1039,9 @@ CALL transaction_test1();
     <para>
      Transactions cannot be ended when an explicit subtransaction is active.
     </para>
-   </sect1>
+   </sect2>
 
-   <sect1 id="pltcl-config">
+   <sect2 id="pltcl-config">
     <title>PL/Tcl Configuration</title>
 
     <para>
@@ -1113,9 +1113,9 @@ CALL transaction_test1();
      </varlistentry>
 
     </variablelist>
-   </sect1>
+   </sect2>
 
-   <sect1 id="pltcl-procnames">
+   <sect2 id="pltcl-procnames">
     <title>Tcl Procedure Names</title>
 
     <para>
@@ -1131,5 +1131,5 @@ CALL transaction_test1();
      when debugging.
     </para>
 
-   </sect1>
- </chapter>
+   </sect2>
+ </sect1>
diff --git a/doc/src/sgml/postgres.sgml b/doc/src/sgml/postgres.sgml
index 5bc47a9e71..f841570bc8 100644
--- a/doc/src/sgml/postgres.sgml
+++ b/doc/src/sgml/postgres.sgml
@@ -215,13 +215,7 @@ break is not needed in a wider output rendering.
   &trigger;
   &event-trigger;
   &rules;
-
-  &xplang;
-  &plsql;
-  &pltcl;
-  &plperl;
-  &plpython;
-
+  &plang;
   &spi;
   &bgworker;
   &logicaldecoding;
diff --git a/doc/src/sgml/xplang.sgml b/doc/src/sgml/xplang.sgml
index 31d403c480..2c0acdc0f7 100644
--- a/doc/src/sgml/xplang.sgml
+++ b/doc/src/sgml/xplang.sgml
@@ -1,44 +1,6 @@
 <!-- doc/src/sgml/xplang.sgml -->
 
- <chapter id="xplang">
-  <title>Procedural Languages</title>
-
-  <indexterm zone="xplang">
-   <primary>procedural language</primary>
-  </indexterm>
-
-  <para>
-   <productname>PostgreSQL</productname> allows user-defined functions
-   to be written in other languages besides SQL and C.  These other
-   languages are generically called <firstterm>procedural
-   languages</firstterm> (<acronym>PL</acronym>s).  For a function
-   written in a procedural language, the database server has
-   no built-in knowledge about how to interpret the function's source
-   text. Instead, the task is passed to a special handler that knows
-   the details of the language.  The handler could either do all the
-   work of parsing, syntax analysis, execution, etc. itself, or it
-   could serve as <quote>glue</quote> between
-   <productname>PostgreSQL</productname> and an existing implementation
-   of a programming language.  The handler itself is a
-   C language function compiled into a shared object and
-   loaded on demand, just like any other C function.
-  </para>
-
-  <para>
-   There are currently four procedural languages available in the
-   standard <productname>PostgreSQL</productname> distribution:
-   <application>PL/pgSQL</application> (<xref linkend="plpgsql"/>),
-   <application>PL/Tcl</application> (<xref linkend="pltcl"/>),
-   <application>PL/Perl</application> (<xref linkend="plperl"/>), and
-   <application>PL/Python</application> (<xref linkend="plpython"/>).
-   There are additional procedural languages available that are not
-   included in the core distribution. <xref linkend="external-projects"/>
-   has information about finding them. In addition other languages can
-   be defined by users; the basics of developing a new procedural
-   language are covered in <xref linkend="plhandler"/>.
-  </para>
-
-  <sect1 id="xplang-install">
+  <sect1 id="xplang">
    <title>Installing Procedural Languages</title>
 
    <para>
@@ -226,5 +188,3 @@ CREATE TRUSTED LANGUAGE plperl
    </para>
 
   </sect1>
-
-</chapter>
-- 
2.39.3 (Apple Git-145)



^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: documentation structure
  2024-03-21 13:38 Re: documentation structure Tom Lane <[email protected]>
  2024-03-21 14:31 ` Re: documentation structure Robert Haas <[email protected]>
@ 2024-03-21 16:16   ` Robert Haas <[email protected]>
  2 siblings, 0 replies; 7+ messages in thread

From: Robert Haas @ 2024-03-21 16:16 UTC (permalink / raw)
  To: Tom Lane <[email protected]>; +Cc: Alvaro Herrera <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers

On Thu, Mar 21, 2024 at 10:31 AM Robert Haas <[email protected]> wrote:
> 0001 and 0002 are changed. Should 0002 use the include-an-entity
> approach as well?

Woops. I meant to say that 0001 and 0002 are *unchanged*.

-- 
Robert Haas
EDB: http://www.enterprisedb.com






^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: documentation structure
  2024-03-21 13:38 Re: documentation structure Tom Lane <[email protected]>
  2024-03-21 14:31 ` Re: documentation structure Robert Haas <[email protected]>
@ 2024-03-21 16:42   ` Alvaro Herrera <[email protected]>
  2 siblings, 0 replies; 7+ messages in thread

From: Alvaro Herrera @ 2024-03-21 16:42 UTC (permalink / raw)
  To: Robert Haas <[email protected]>; +Cc: Tom Lane <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers

On 2024-Mar-21, Robert Haas wrote:

> On Thu, Mar 21, 2024 at 9:38 AM Tom Lane <[email protected]> wrote:
> > I'd follow the extend.sgml precedent: have a file corresponding to the
> > chapter and containing any top-level text we need, then that includes
> > a file per sect1.
> 
> OK, here's a new patch set. I've revised 0003 and 0004 to use this
> approach, 

Great, thanks.  Looking at the index in the PDF after (only) 0003, we
now have this structure

62. Table Access Method Interface Definition ....................................................... 2475
63. Index Access Method Interface Definition ....................................................... 2476
63.1. Basic API Structure for Indexes .......................................................... 2476
63.2. Index Access Method Functions .......................................................... 2479
63.3. Index Scanning ................................................................................ 2485
63.4. Index Locking Considerations ............................................................. 2486
63.5. Index Uniqueness Checks .................................................................. 2487
63.6. Index Cost Estimation Functions ......................................................... 2489
64. Generic WAL Records ................................................................................. 2492
65. Custom WAL Resource Managers ................................................................. 2494
66. Built-in Index Access Methods ...................................................................... 2496

which is a bit odd: why are the two WAL chapters in the middle of the
chapters 62 and 63 talking about AMs?  Maybe put 66 right after 63
instead.    Also, is it really better to have 62/63 first and 66
later?  It sounds to me like 66 is more user-oriented and the other two
are developer-oriented, so I'm inclined to suggest putting them the
other way around, but I'm not really sure about this.  (Also, starting
chapter 66 straight with 66.1 BTree without any intro text looks a bit
odd; maybe one short introductory paragraph is sufficient?)

> and I've added a new 0005 that does essentially the same
> thing for the PL chapters.

I was looking at the PL chapters earlier today too, wondering whether
this would be valuable; but I worry that there are too many
sub-sub-sections there, so it could end up being a bit messy.  I didn't
look at the resulting output though.

> 0001 and 0002 are [un]changed. Should 0002 use the include-an-entity
> approach as well?

Shrug, I wouldn't, doesn't look worth it.

-- 
Álvaro Herrera               48°01'N 7°57'E  —  https://www.EnterpriseDB.com/
"No es bueno caminar con un hombre muerto"






^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: documentation structure
  2024-03-21 13:38 Re: documentation structure Tom Lane <[email protected]>
  2024-03-21 14:31 ` Re: documentation structure Robert Haas <[email protected]>
@ 2024-03-21 23:40   ` Peter Eisentraut <[email protected]>
  2024-03-22 13:59     ` Re: documentation structure Robert Haas <[email protected]>
  2 siblings, 1 reply; 7+ messages in thread

From: Peter Eisentraut @ 2024-03-21 23:40 UTC (permalink / raw)
  To: Robert Haas <[email protected]>; Tom Lane <[email protected]>; +Cc: Alvaro Herrera <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers

On 21.03.24 15:31, Robert Haas wrote:
> On Thu, Mar 21, 2024 at 9:38 AM Tom Lane <[email protected]> wrote:
>> I'd follow the extend.sgml precedent: have a file corresponding to the
>> chapter and containing any top-level text we need, then that includes
>> a file per sect1.
> 
> OK, here's a new patch set. I've revised 0003 and 0004 to use this
> approach, and I've added a new 0005 that does essentially the same
> thing for the PL chapters.

I'm highly against this.  If I want to read about PL/Python, why should 
I have to wade through PL/Perl and PL/Tcl?

I think, abstractly, in a book, PL/Python should be a chapter of its 
own.  Just like GiST should be a chapter of its own.  Because they are 
self-contained topics.







^ permalink  raw  reply  [nested|flat] 7+ messages in thread

* Re: documentation structure
  2024-03-21 13:38 Re: documentation structure Tom Lane <[email protected]>
  2024-03-21 14:31 ` Re: documentation structure Robert Haas <[email protected]>
  2024-03-21 23:40   ` Re: documentation structure Peter Eisentraut <[email protected]>
@ 2024-03-22 13:59     ` Robert Haas <[email protected]>
  0 siblings, 0 replies; 7+ messages in thread

From: Robert Haas @ 2024-03-22 13:59 UTC (permalink / raw)
  To: Peter Eisentraut <[email protected]>; +Cc: Tom Lane <[email protected]>; Alvaro Herrera <[email protected]>; Andrew Dunstan <[email protected]>; pgsql-hackers

On Thu, Mar 21, 2024 at 7:40 PM Peter Eisentraut <[email protected]> wrote:
> I'm highly against this.  If I want to read about PL/Python, why should
> I have to wade through PL/Perl and PL/Tcl?
>
> I think, abstractly, in a book, PL/Python should be a chapter of its
> own.  Just like GiST should be a chapter of its own.  Because they are
> self-contained topics.

On the other hand, in a book, chapters tend to be of relatively
uniform length. People don't usually write a book with some chapters
that are 100+ pages long, and others that are a single page, or even
just a couple of sentences. I mean, I'm sure it's been done, but it's
not a normal way to write a book.

And I don't believe that if someone were writing a physical book about
PostgreSQL from scratch, they'd ever end up with a top-level chapter
that looks anything like our GiST chapter. All of the index AM
chapters are quite obviously clones of each other, and they're all
quite short. Surely you'd make them sections within a chapter, not
entire chapters.

I do agree that PL/pgsql is more arguable. I can imagine somebody
writing a book about PostgreSQL and choosing to make that topic into a
whole chapter.

However, I also think that people don't make decisions about what
should be a chapter in a vacuum. If you've got 100 people writing a
book together, which is essentially what we actually do have, and each
of those people makes decisions in isolation about what is worthy of
being a chapter, then you end up with exactly the kind of mess that we
now have. Some chapters are long and some are short. Some are
well-written and some are poorly written. Some are updated regularly
and others have hardly been touched in a decade. Books have editors to
straighten out those kinds of inconsistencies so that there's some
uniformity to the product as a whole.

The problem with that, of course, is that it invites bike-shedding. As
you say, every decision that is reflected in our documentation was
made for some reason, and most of them will have been made by
prominent, active committers. So discussions about how to improve
things can easily bog down even when people agree on the overall
goals, simply because few individual changes find consensus. I hope
that doesn't happen here, because I think most people who have
commented so far agree that there is a problem here and that we should
try to fix it. Let's not let the perfect be the enemy of the good.

-- 
Robert Haas
EDB: http://www.enterprisedb.com






^ permalink  raw  reply  [nested|flat] 7+ messages in thread


end of thread, other threads:[~2024-03-22 13:59 UTC | newest]

Thread overview: 7+ messages (download: mbox mbox.gz follow: Atom feed)
-- links below jump to the message on this page --
2021-03-08 06:43 [PATCH 03/10] Make sure published XIDs are persistent Kyotaro Horiguchi <[email protected]>
2024-03-21 13:38 Re: documentation structure Tom Lane <[email protected]>
2024-03-21 14:31 ` Re: documentation structure Robert Haas <[email protected]>
2024-03-21 16:16   ` Re: documentation structure Robert Haas <[email protected]>
2024-03-21 16:42   ` Re: documentation structure Alvaro Herrera <[email protected]>
2024-03-21 23:40   ` Re: documentation structure Peter Eisentraut <[email protected]>
2024-03-22 13:59     ` Re: documentation structure Robert Haas <[email protected]>

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox