Hi all After spending a while working on the BDR extension I've found that the current documentation on the SPI and bgworkers could use some more detail.
In the process I've put cross reference labels in for most chapter headings, as I got sick of seeing "Chapter 33" (or whatever) everywhere in the docs. I'd like to progressively add them to every section, refentry, chapter, etc that has an id. I hope this is useful. -- Craig Ringer http://www.2ndQuadrant.com/ PostgreSQL Development, 24x7 Support, Training & Services
From c73d1303cb3474ccc799eeda252eeef1fc3d9026 Mon Sep 17 00:00:00 2001 From: Craig Ringer <cr...@2ndquadrant.com> Date: Mon, 16 Feb 2015 18:17:48 +1300 Subject: [PATCH 1/4] Add xreflabel to most chapter entries --- doc/src/sgml/array.sgml | 2 +- doc/src/sgml/backup.sgml | 2 +- doc/src/sgml/brin.sgml | 2 +- doc/src/sgml/catalogs.sgml | 2 +- doc/src/sgml/client-auth.sgml | 2 +- doc/src/sgml/config.sgml | 2 +- doc/src/sgml/datatype.sgml | 2 +- doc/src/sgml/ddl.sgml | 2 +- doc/src/sgml/diskusage.sgml | 2 +- doc/src/sgml/dml.sgml | 2 +- doc/src/sgml/errcodes.sgml | 2 +- doc/src/sgml/event-trigger.sgml | 2 +- doc/src/sgml/extend.sgml | 2 +- doc/src/sgml/features.sgml | 2 +- doc/src/sgml/func.sgml | 2 +- doc/src/sgml/gin.sgml | 2 +- doc/src/sgml/gist.sgml | 2 +- doc/src/sgml/high-availability.sgml | 2 +- doc/src/sgml/indices.sgml | 2 +- doc/src/sgml/information_schema.sgml | 2 +- doc/src/sgml/json.sgml | 2 +- doc/src/sgml/keywords.sgml | 2 +- doc/src/sgml/libpq.sgml | 2 +- doc/src/sgml/lobj.sgml | 2 +- doc/src/sgml/logicaldecoding.sgml | 2 +- doc/src/sgml/maintenance.sgml | 2 +- doc/src/sgml/manage-ag.sgml | 2 +- doc/src/sgml/monitoring.sgml | 2 +- doc/src/sgml/mvcc.sgml | 2 +- doc/src/sgml/perform.sgml | 2 +- doc/src/sgml/plperl.sgml | 2 +- doc/src/sgml/plpgsql.sgml | 2 +- doc/src/sgml/plpython.sgml | 2 +- doc/src/sgml/pltcl.sgml | 2 +- doc/src/sgml/rangetypes.sgml | 2 +- doc/src/sgml/recovery-config.sgml | 2 +- doc/src/sgml/reference.sgml | 2 +- doc/src/sgml/regress.sgml | 2 +- doc/src/sgml/release.sgml | 2 +- doc/src/sgml/rowtypes.sgml | 2 +- doc/src/sgml/rules.sgml | 2 +- doc/src/sgml/runtime.sgml | 2 +- doc/src/sgml/spgist.sgml | 2 +- doc/src/sgml/spi.sgml | 4 ++-- doc/src/sgml/sql.sgml | 2 +- doc/src/sgml/storage.sgml | 2 +- doc/src/sgml/syntax.sgml | 2 +- doc/src/sgml/textsearch.sgml | 2 +- doc/src/sgml/trigger.sgml | 2 +- doc/src/sgml/typeconv.sgml | 2 +- doc/src/sgml/user-manag.sgml | 2 +- doc/src/sgml/wal.sgml | 2 +- doc/src/sgml/xaggr.sgml | 2 +- doc/src/sgml/xfunc.sgml | 6 +++--- doc/src/sgml/xoper.sgml | 2 +- doc/src/sgml/xplang.sgml | 2 +- doc/src/sgml/xtypes.sgml | 2 +- 57 files changed, 60 insertions(+), 60 deletions(-) diff --git a/doc/src/sgml/array.sgml b/doc/src/sgml/array.sgml index 9ea1068..7c68828 100644 --- a/doc/src/sgml/array.sgml +++ b/doc/src/sgml/array.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/array.sgml --> -<sect1 id="arrays"> +<sect1 id="arrays" xreflabel="Arrays"> <title>Arrays</title> <indexterm> diff --git a/doc/src/sgml/backup.sgml b/doc/src/sgml/backup.sgml index 07ca0dc..c1ade01 100644 --- a/doc/src/sgml/backup.sgml +++ b/doc/src/sgml/backup.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/backup.sgml --> -<chapter id="backup"> +<chapter id="backup" xreflabel="Backup and Restore"> <title>Backup and Restore</title> <indexterm zone="backup"><primary>backup</></> diff --git a/doc/src/sgml/brin.sgml b/doc/src/sgml/brin.sgml index 1ac282c..ae6f3f5 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"> +<chapter id="BRIN" xreflabel="BRIN Indexes"> <title>BRIN Indexes</title> <indexterm> diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 515a40e..599d524 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -3,7 +3,7 @@ Documentation of the system catalogs, directed toward PostgreSQL developers --> -<chapter id="catalogs"> +<chapter id="catalogs" xreflabel="System Catalogs"> <title>System Catalogs</title> <para> diff --git a/doc/src/sgml/client-auth.sgml b/doc/src/sgml/client-auth.sgml index 7704f73..22cfc05 100644 --- a/doc/src/sgml/client-auth.sgml +++ b/doc/src/sgml/client-auth.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/client-auth.sgml --> -<chapter id="client-authentication"> +<chapter id="client-authentication" xreflabel="Client Authentication"> <title>Client Authentication</title> <indexterm zone="client-authentication"> diff --git a/doc/src/sgml/config.sgml b/doc/src/sgml/config.sgml index 6bcb106..7d86014 100644 --- a/doc/src/sgml/config.sgml +++ b/doc/src/sgml/config.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/config.sgml --> -<chapter id="runtime-config"> +<chapter id="runtime-config" xreflabel="Server Configuration"> <title>Server Configuration</title> <indexterm> diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml index edf636b..2c2dc9d 100644 --- a/doc/src/sgml/datatype.sgml +++ b/doc/src/sgml/datatype.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/datatype.sgml --> - <chapter id="datatype"> + <chapter id="datatype" xreflabel="Data Types"> <title>Data Types</title> <indexterm zone="datatype"> diff --git a/doc/src/sgml/ddl.sgml b/doc/src/sgml/ddl.sgml index 570a003..964e158 100644 --- a/doc/src/sgml/ddl.sgml +++ b/doc/src/sgml/ddl.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/ddl.sgml --> -<chapter id="ddl"> +<chapter id="ddl" xreflabel="Data Definition"> <title>Data Definition</title> <para> diff --git a/doc/src/sgml/diskusage.sgml b/doc/src/sgml/diskusage.sgml index 461deb9..20ee0b9 100644 --- a/doc/src/sgml/diskusage.sgml +++ b/doc/src/sgml/diskusage.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/diskusage.sgml --> -<chapter id="diskusage"> +<chapter id="diskusage" xreflabel="Monitoring Disk Usage"> <title>Monitoring Disk Usage</title> <para> diff --git a/doc/src/sgml/dml.sgml b/doc/src/sgml/dml.sgml index cd36a73..4472957 100644 --- a/doc/src/sgml/dml.sgml +++ b/doc/src/sgml/dml.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/dml.sgml --> -<chapter id="dml"> +<chapter id="dml" xreflabel="Data Manipulation"> <title>Data Manipulation</title> <remark> diff --git a/doc/src/sgml/errcodes.sgml b/doc/src/sgml/errcodes.sgml index 40b4191..31116c2 100644 --- a/doc/src/sgml/errcodes.sgml +++ b/doc/src/sgml/errcodes.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/errcodes.sgml --> -<appendix id="errcodes-appendix"> +<appendix id="errcodes-appendix" xreflabel="Error Codes"> <title><productname>PostgreSQL</productname> Error Codes</title> <indexterm zone="errcodes-appendix"> diff --git a/doc/src/sgml/event-trigger.sgml b/doc/src/sgml/event-trigger.sgml index 156c463..a0d3505 100644 --- a/doc/src/sgml/event-trigger.sgml +++ b/doc/src/sgml/event-trigger.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/event-trigger.sgml --> - <chapter id="event-triggers"> + <chapter id="event-triggers" xreflabel="Event Triggers"> <title>Event Triggers</title> <indexterm zone="event-triggers"> diff --git a/doc/src/sgml/extend.sgml b/doc/src/sgml/extend.sgml index be10252..48814bc 100644 --- a/doc/src/sgml/extend.sgml +++ b/doc/src/sgml/extend.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/extend.sgml --> - <chapter id="extend"> + <chapter id="extend" xreflabel="Extending SQL"> <title>Extending <acronym>SQL</acronym></title> <indexterm zone="extend"> diff --git a/doc/src/sgml/features.sgml b/doc/src/sgml/features.sgml index 6c22d69..e4c6b3f 100644 --- a/doc/src/sgml/features.sgml +++ b/doc/src/sgml/features.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/features.sgml --> -<appendix id="features"> +<appendix id="features" xreflabel="SQL Conformance"> <title>SQL Conformance</title> <para> diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml index da2ed67..fd8f642 100644 --- a/doc/src/sgml/func.sgml +++ b/doc/src/sgml/func.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/func.sgml --> - <chapter id="functions"> + <chapter id="functions" xreflabel="Functions and Operators"> <title>Functions and Operators</title> <indexterm zone="functions"> diff --git a/doc/src/sgml/gin.sgml b/doc/src/sgml/gin.sgml index 262f1e4..28e7d5e 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"> +<chapter id="GIN" xreflabel="GIN Indexes"> <title>GIN Indexes</title> <indexterm> diff --git a/doc/src/sgml/gist.sgml b/doc/src/sgml/gist.sgml index 31ce279..50721f3 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"> +<chapter id="GiST" xreflabel="GiST indexes"> <title>GiST Indexes</title> <indexterm> diff --git a/doc/src/sgml/high-availability.sgml b/doc/src/sgml/high-availability.sgml index d249959..d07b6e5 100644 --- a/doc/src/sgml/high-availability.sgml +++ b/doc/src/sgml/high-availability.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/high-availability.sgml --> -<chapter id="high-availability"> +<chapter id="high-availability" xreflabel="High Availability, Load Balancing, and Replication"> <title>High Availability, Load Balancing, and Replication</title> <indexterm><primary>high availability</></> diff --git a/doc/src/sgml/indices.sgml b/doc/src/sgml/indices.sgml index b73463a..585241d 100644 --- a/doc/src/sgml/indices.sgml +++ b/doc/src/sgml/indices.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/indices.sgml --> -<chapter id="indexes"> +<chapter id="indexes" xreflabel="Indexes"> <title>Indexes</title> <indexterm zone="indexes"> diff --git a/doc/src/sgml/information_schema.sgml b/doc/src/sgml/information_schema.sgml index 22f43c8..8a3b317 100644 --- a/doc/src/sgml/information_schema.sgml +++ b/doc/src/sgml/information_schema.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/information_schema.sgml --> -<chapter id="information-schema"> +<chapter id="information-schema" xreflabel="The Information Schema"> <title>The Information Schema</title> <indexterm zone="information-schema"> diff --git a/doc/src/sgml/json.sgml b/doc/src/sgml/json.sgml index 6282ab8..1833e76 100644 --- a/doc/src/sgml/json.sgml +++ b/doc/src/sgml/json.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/json.sgml --> -<sect1 id="datatype-json"> +<sect1 id="datatype-json" xreflabel="JSON types"> <title><acronym>JSON</> Types</title> <indexterm zone="datatype-json"> diff --git a/doc/src/sgml/keywords.sgml b/doc/src/sgml/keywords.sgml index b0dfd5f..f8345bc 100644 --- a/doc/src/sgml/keywords.sgml +++ b/doc/src/sgml/keywords.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/keywords.sgml --> -<appendix id="sql-keywords-appendix"> +<appendix id="sql-keywords-appendix" xreflabel="SQL Key Words"> <title><acronym>SQL</acronym> Key Words</title> <indexterm zone="sql-keywords-appendix"> diff --git a/doc/src/sgml/libpq.sgml b/doc/src/sgml/libpq.sgml index 39aede4..92b4a92 100644 --- a/doc/src/sgml/libpq.sgml +++ b/doc/src/sgml/libpq.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/libpq.sgml --> -<chapter id="libpq"> +<chapter id="libpq" xreflabel="libpq"> <title><application>libpq</application> - C Library</title> <indexterm zone="libpq"> diff --git a/doc/src/sgml/lobj.sgml b/doc/src/sgml/lobj.sgml index d6fb8c5..cd5df8b 100644 --- a/doc/src/sgml/lobj.sgml +++ b/doc/src/sgml/lobj.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/lobj.sgml --> - <chapter id="largeObjects"> + <chapter id="largeObjects" xreflabel="Large Objects"> <title>Large Objects</title> <indexterm zone="largeobjects"><primary>large object</></> diff --git a/doc/src/sgml/logicaldecoding.sgml b/doc/src/sgml/logicaldecoding.sgml index 3650567..7a70270 100644 --- a/doc/src/sgml/logicaldecoding.sgml +++ b/doc/src/sgml/logicaldecoding.sgml @@ -1,5 +1,5 @@ <!-- doc/src/sgml/logicaldecoding.sgml --> - <chapter id="logicaldecoding"> + <chapter id="logicaldecoding" xreflabel="Logical Decoding"> <title>Logical Decoding</title> <indexterm zone="logicaldecoding"> <primary>Logical Decoding</primary> diff --git a/doc/src/sgml/maintenance.sgml b/doc/src/sgml/maintenance.sgml index 8764e00..8d8bbad 100644 --- a/doc/src/sgml/maintenance.sgml +++ b/doc/src/sgml/maintenance.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/maintenance.sgml --> -<chapter id="maintenance"> +<chapter id="maintenance" xreflabel="Routine Database Maintenance Tasks"> <title>Routine Database Maintenance Tasks</title> <indexterm zone="maintenance"> diff --git a/doc/src/sgml/manage-ag.sgml b/doc/src/sgml/manage-ag.sgml index 78ec509..795d407 100644 --- a/doc/src/sgml/manage-ag.sgml +++ b/doc/src/sgml/manage-ag.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/manage-ag.sgml --> -<chapter id="managing-databases"> +<chapter id="managing-databases" xreflabel="Managing Databases"> <title>Managing Databases</title> <indexterm zone="managing-databases"><primary>database</></> diff --git a/doc/src/sgml/monitoring.sgml b/doc/src/sgml/monitoring.sgml index 3ce7e80..f062fc3 100644 --- a/doc/src/sgml/monitoring.sgml +++ b/doc/src/sgml/monitoring.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/monitoring.sgml --> -<chapter id="monitoring"> +<chapter id="monitoring" xreflabel="Monitoring Database Activity"> <title>Monitoring Database Activity</title> <indexterm zone="monitoring"> diff --git a/doc/src/sgml/mvcc.sgml b/doc/src/sgml/mvcc.sgml index a0d6867..00dcdf9 100644 --- a/doc/src/sgml/mvcc.sgml +++ b/doc/src/sgml/mvcc.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/mvcc.sgml --> - <chapter id="mvcc"> + <chapter id="mvcc" xreflabel="Concurrency Control"> <title>Concurrency Control</title> <indexterm> diff --git a/doc/src/sgml/perform.sgml b/doc/src/sgml/perform.sgml index 5a087fb..0b1b1c3 100644 --- a/doc/src/sgml/perform.sgml +++ b/doc/src/sgml/perform.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/perform.sgml --> - <chapter id="performance-tips"> + <chapter id="performance-tips" xreflabel="Peformance Tips"> <title>Performance Tips</title> <indexterm zone="performance-tips"> diff --git a/doc/src/sgml/plperl.sgml b/doc/src/sgml/plperl.sgml index 9117769..6f37b82 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"> + <chapter id="plperl" xreflabel="PL/Perl"> <title>PL/Perl - Perl Procedural Language</title> <indexterm zone="plperl"> diff --git a/doc/src/sgml/plpgsql.sgml b/doc/src/sgml/plpgsql.sgml index 69a0885..9837a42 100644 --- a/doc/src/sgml/plpgsql.sgml +++ b/doc/src/sgml/plpgsql.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/plpgsql.sgml --> -<chapter id="plpgsql"> +<chapter id="plpgsql" xreflabel="PL/PgSQL"> <title><application>PL/pgSQL</application> - <acronym>SQL</acronym> Procedural Language</title> <indexterm zone="plpgsql"> diff --git a/doc/src/sgml/plpython.sgml b/doc/src/sgml/plpython.sgml index c838c7b..50f6d51 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"> +<chapter id="plpython" xreflabel="PL/Python"> <title>PL/Python - Python Procedural Language</title> <indexterm zone="plpython"><primary>PL/Python</></> diff --git a/doc/src/sgml/pltcl.sgml b/doc/src/sgml/pltcl.sgml index d2175d5..94e96d8 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"> + <chapter id="pltcl" xreflabel="PL/TCL"> <title>PL/Tcl - Tcl Procedural Language</title> <indexterm zone="pltcl"> diff --git a/doc/src/sgml/rangetypes.sgml b/doc/src/sgml/rangetypes.sgml index d112561..d7e613a 100644 --- a/doc/src/sgml/rangetypes.sgml +++ b/doc/src/sgml/rangetypes.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/rangetypes.sgml --> -<sect1 id="rangetypes"> +<sect1 id="rangetypes" xreflabel="Range Types"> <title>Range Types</title> <indexterm> diff --git a/doc/src/sgml/recovery-config.sgml b/doc/src/sgml/recovery-config.sgml index 0c64ff2..7c99c2d 100644 --- a/doc/src/sgml/recovery-config.sgml +++ b/doc/src/sgml/recovery-config.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/recovery-config.sgml --> -<chapter id="recovery-config"> +<chapter id="recovery-config" xreflabel="Recovery Configuration"> <title>Recovery Configuration</title> <indexterm> diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml index 10c9a6d..389dbcd 100644 --- a/doc/src/sgml/reference.sgml +++ b/doc/src/sgml/reference.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/reference.sgml --> -<part id="reference"> +<part id="reference" xreflabel="Reference"> <title>Reference</title> <partintro> diff --git a/doc/src/sgml/regress.sgml b/doc/src/sgml/regress.sgml index 504d8da..a7b0f41 100644 --- a/doc/src/sgml/regress.sgml +++ b/doc/src/sgml/regress.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/regress.sgml --> - <chapter id="regress"> + <chapter id="regress" xreflabel="Regression Tests"> <title>Regression Tests</title> <indexterm zone="regress"> diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml index 8385220..8423209 100644 --- a/doc/src/sgml/release.sgml +++ b/doc/src/sgml/release.sgml @@ -38,7 +38,7 @@ For new features, add links to the documentation sections. --> -<appendix id="release"> +<appendix id="release" xreflabel="Release Notes"> <title>Release Notes</title> <para> diff --git a/doc/src/sgml/rowtypes.sgml b/doc/src/sgml/rowtypes.sgml index 605dc71..cad88a5 100644 --- a/doc/src/sgml/rowtypes.sgml +++ b/doc/src/sgml/rowtypes.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/rowtypes.sgml --> -<sect1 id="rowtypes"> +<sect1 id="rowtypes" xreflabel="Composite Types"> <title>Composite Types</title> <indexterm> diff --git a/doc/src/sgml/rules.sgml b/doc/src/sgml/rules.sgml index 973db74..2ac30e9 100644 --- a/doc/src/sgml/rules.sgml +++ b/doc/src/sgml/rules.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/rules.sgml --> -<chapter id="rules"> +<chapter id="rules" xreflabel="The Rule System"> <title>The Rule System</title> <indexterm zone="rules"> diff --git a/doc/src/sgml/runtime.sgml b/doc/src/sgml/runtime.sgml index 026850a..d90c2ae 100644 --- a/doc/src/sgml/runtime.sgml +++ b/doc/src/sgml/runtime.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/runtime.sgml --> -<chapter id="runtime"> +<chapter id="runtime" xreflabel="Server Setup and Operation"> <title>Server Setup and Operation</title> <para> diff --git a/doc/src/sgml/spgist.sgml b/doc/src/sgml/spgist.sgml index 56827e5..424785f 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"> +<chapter id="SPGiST" xreflabel="SP-GiST indexes"> <title>SP-GiST Indexes</title> <indexterm> diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml index c099fcf..cb85086 100644 --- a/doc/src/sgml/spi.sgml +++ b/doc/src/sgml/spi.sgml @@ -1,7 +1,7 @@ <!-- doc/src/sgml/spi.sgml --> -<chapter id="spi"> - <title>Server Programming Interface</title> +<chapter id="spi" xreflabel="Server Programming Interface (SPI)"> + <title>Server Programming Interface (<acronym>SPI</acronym>)</title> <indexterm zone="spi"> <primary>SPI</primary> diff --git a/doc/src/sgml/sql.sgml b/doc/src/sgml/sql.sgml index 57396d7..88534e8 100644 --- a/doc/src/sgml/sql.sgml +++ b/doc/src/sgml/sql.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/sql.sgml --> - <chapter id="sql-intro"> + <chapter id="sql-intro" xreflabel="SQL"> <title>SQL</title> <abstract> diff --git a/doc/src/sgml/storage.sgml b/doc/src/sgml/storage.sgml index cb76b98..614798e 100644 --- a/doc/src/sgml/storage.sgml +++ b/doc/src/sgml/storage.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/storage.sgml --> -<chapter id="storage"> +<chapter id="storage" xreflabel="Database Physical Storage"> <title>Database Physical Storage</title> diff --git a/doc/src/sgml/syntax.sgml b/doc/src/sgml/syntax.sgml index 4b81b08..4d1f075 100644 --- a/doc/src/sgml/syntax.sgml +++ b/doc/src/sgml/syntax.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/syntax.sgml --> -<chapter id="sql-syntax"> +<chapter id="sql-syntax" xreflabel="SQL Syntax"> <title>SQL Syntax</title> <indexterm zone="sql-syntax"> diff --git a/doc/src/sgml/textsearch.sgml b/doc/src/sgml/textsearch.sgml index 0bc7e7b..5beb7fa 100644 --- a/doc/src/sgml/textsearch.sgml +++ b/doc/src/sgml/textsearch.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/textsearch.sgml --> -<chapter id="textsearch"> +<chapter id="textsearch" xreflabel="Full Text Search"> <title>Full Text Search</title> <indexterm zone="textsearch"> diff --git a/doc/src/sgml/trigger.sgml b/doc/src/sgml/trigger.sgml index f94aea1..685bce0 100644 --- a/doc/src/sgml/trigger.sgml +++ b/doc/src/sgml/trigger.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/trigger.sgml --> - <chapter id="triggers"> + <chapter id="triggers" xreflabel="Triggers"> <title>Triggers</title> <indexterm zone="triggers"> diff --git a/doc/src/sgml/typeconv.sgml b/doc/src/sgml/typeconv.sgml index ed37772..5381a39 100644 --- a/doc/src/sgml/typeconv.sgml +++ b/doc/src/sgml/typeconv.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/typeconv.sgml --> -<chapter id="typeconv"> +<chapter id="typeconv" xreflabel="Type Conversion"> <title>Type Conversion</title> <indexterm zone="typeconv"> diff --git a/doc/src/sgml/user-manag.sgml b/doc/src/sgml/user-manag.sgml index 177ac7a..eb1a887 100644 --- a/doc/src/sgml/user-manag.sgml +++ b/doc/src/sgml/user-manag.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/user-manag.sgml --> -<chapter id="user-manag"> +<chapter id="user-manag" xreflabel="Database Roles"> <title>Database Roles</title> <para> diff --git a/doc/src/sgml/wal.sgml b/doc/src/sgml/wal.sgml index 1254c03..0f237cc 100644 --- a/doc/src/sgml/wal.sgml +++ b/doc/src/sgml/wal.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/wal.sgml --> -<chapter id="wal"> +<chapter id="wal" xreflabel="Reliability and the Write-Ahead Log"> <title>Reliability and the Write-Ahead Log</title> <para> diff --git a/doc/src/sgml/xaggr.sgml b/doc/src/sgml/xaggr.sgml index ef7cff4..7709764 100644 --- a/doc/src/sgml/xaggr.sgml +++ b/doc/src/sgml/xaggr.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/xaggr.sgml --> - <sect1 id="xaggr"> + <sect1 id="xaggr" xreflabel="User-defined Aggregates"> <title>User-defined Aggregates</title> <indexterm zone="xaggr"> diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index f40504c..6eada92 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/xfunc.sgml --> - <sect1 id="xfunc"> + <sect1 id="xfunc" xreflabel="user-defined functions"> <title>User-defined Functions</title> <indexterm zone="xfunc"> @@ -3304,7 +3304,7 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray </para> </sect2> - <sect2> + <sect2 id="xfunc-shmem-lwlocks" xreflabel="shared memory and LWLocks in user-defined C functions"> <title>Shared Memory and LWLocks</title> <para> @@ -3350,7 +3350,7 @@ if (!ptr) </para> </sect2> - <sect2 id="extend-Cpp"> + <sect2 id="extend-Cpp" xreflabel="using C++ for extensibility"> <title>Using C++ for Extensibility</title> <indexterm zone="extend-Cpp"> diff --git a/doc/src/sgml/xoper.sgml b/doc/src/sgml/xoper.sgml index 8568e21..c6fcbd8 100644 --- a/doc/src/sgml/xoper.sgml +++ b/doc/src/sgml/xoper.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/xoper.sgml --> - <sect1 id="xoper"> + <sect1 id="xoper" xreflabel="User-defined Operators"> <title>User-defined Operators</title> <indexterm zone="xoper"> diff --git a/doc/src/sgml/xplang.sgml b/doc/src/sgml/xplang.sgml index 68220bf..55ba40a 100644 --- a/doc/src/sgml/xplang.sgml +++ b/doc/src/sgml/xplang.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/xplang.sgml --> - <chapter id="xplang"> + <chapter id="xplang" xreflabel="Procedural Languages"> <title>Procedural Languages</title> <indexterm zone="xplang"> diff --git a/doc/src/sgml/xtypes.sgml b/doc/src/sgml/xtypes.sgml index e1340ba..44340ab 100644 --- a/doc/src/sgml/xtypes.sgml +++ b/doc/src/sgml/xtypes.sgml @@ -1,6 +1,6 @@ <!-- doc/src/sgml/xtypes.sgml --> - <sect1 id="xtypes"> + <sect1 id="xtypes" xreflabel="User-defined Types"> <title>User-defined Types</title> <indexterm zone="xtypes"> -- 2.1.0
From 6e2103b211aee44780c6106e307ea4a561d11fde Mon Sep 17 00:00:00 2001 From: Craig Ringer <cr...@2ndquadrant.com> Date: Mon, 16 Feb 2015 18:17:59 +1300 Subject: [PATCH 2/4] Document how to build with the website style --- doc/src/sgml/docguide.sgml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/src/sgml/docguide.sgml b/doc/src/sgml/docguide.sgml index e0ae262..6f896b5 100644 --- a/doc/src/sgml/docguide.sgml +++ b/doc/src/sgml/docguide.sgml @@ -584,6 +584,15 @@ checking for osx... osx </para> <para> + To produce HTML documentation with the stylesheet used on <ulink + url="http://postgresql.org/docs/current">postgresql.org</> instead of the + default simple style use: +<screen> +<prompt>doc/src/sgml$ </prompt><userinput>make STYLE=website html</userinput> +</screen> + </para> + + <para> To create a proper index, the build might process several identical stages. If you do not care about the index, and just want to proof-read the output, use <literal>draft</>: -- 2.1.0
From fc93f92fbd1a72534c671ea3f76d4f7ec9ddeaa5 Mon Sep 17 00:00:00 2001 From: Craig Ringer <cr...@2ndquadrant.com> Date: Mon, 16 Feb 2015 18:37:02 +1300 Subject: [PATCH 3/4] Add some index terms in function docs --- doc/src/sgml/xfunc.sgml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 6eada92..6437ab1 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -3307,6 +3307,15 @@ CREATE FUNCTION make_array(anyelement) RETURNS anyarray <sect2 id="xfunc-shmem-lwlocks" xreflabel="shared memory and LWLocks in user-defined C functions"> <title>Shared Memory and LWLocks</title> + <indexterm zone="xfunc-shmem-lwlocks"> + <primary>Shared memory in extensions</primary> + </indexterm> + + <indexterm zone="xfunc-shmem-lwlocks"> + <primary>LWLocks (extensions)</primary> + <secondary>Lightweight locks (extensions)</secondary> + </indexterm> + <para> Add-ins can reserve LWLocks and an allocation of shared memory on server startup. The add-in's shared library must be preloaded by specifying -- 2.1.0
From 04e1cbe49268e22886e2b30fe412fef0cb9dcc65 Mon Sep 17 00:00:00 2001 From: Craig Ringer <cr...@2ndquadrant.com> Date: Mon, 16 Feb 2015 18:37:19 +1300 Subject: [PATCH 4/4] Document SPI use from bgworkers in greater detail --- doc/src/sgml/bgworker.sgml | 164 +++++++++++++++++++++++++++-------- doc/src/sgml/contrib.sgml | 1 + doc/src/sgml/example-worker-spi.sgml | 26 ++++++ doc/src/sgml/filelist.sgml | 1 + doc/src/sgml/spi.sgml | 151 +++++++++++++++++++++++++++++++- doc/src/sgml/xfunc.sgml | 54 ++++++++++++ 6 files changed, 357 insertions(+), 40 deletions(-) create mode 100644 doc/src/sgml/example-worker-spi.sgml diff --git a/doc/src/sgml/bgworker.sgml b/doc/src/sgml/bgworker.sgml index ef28f72..d0e7dc0 100644 --- a/doc/src/sgml/bgworker.sgml +++ b/doc/src/sgml/bgworker.sgml @@ -34,18 +34,21 @@ <productname>PostgreSQL</> is started by including the module name in <varname>shared_preload_libraries</>. A module wishing to run a background worker can register it by calling + <indexterm><primary>RegisterBackgroundWorker</primary></indexterm> <function>RegisterBackgroundWorker(<type>BackgroundWorker *worker</type>)</function> from its <function>_PG_init()</>. Background workers can also be started after the system is up and running by calling the function + <indexterm><primary>RegisterDynamicBackgroundWorker</primary></indexterm> <function>RegisterDynamicBackgroundWorker(<type>BackgroundWorker *worker, BackgroundWorkerHandle **handle</type>)</function>. Unlike <function>RegisterBackgroundWorker</>, which can only be called from within the postmaster, <function>RegisterDynamicBackgroundWorker</function> must be - called from a regular backend. + called from a regular backend (which might be another background worker). </para> <para> - The structure <structname>BackgroundWorker</structname> is defined thus: + The structure <indexterm><primary>BackgroundWorker</primary></indexterm> + <structname>BackgroundWorker</structname> is defined thus: <programlisting> typedef void (*bgworker_main_type)(Datum main_arg); typedef struct BackgroundWorker @@ -64,22 +67,46 @@ typedef struct BackgroundWorker </para> <para> - <structfield>bgw_name</> is a string to be used in log messages, process + <indexterm><primary>bgw_name</></><structfield>bgw_name</> is a string to be used in log messages, process listings and similar contexts. </para> <para> <structfield>bgw_flags</> is a bitwise-or'd bit mask indicating the - capabilities that the module wants. Possible values are - <literal>BGWORKER_SHMEM_ACCESS</literal> (requesting shared memory access) - and <literal>BGWORKER_BACKEND_DATABASE_CONNECTION</literal> (requesting the - ability to establish a database connection, through which it can later run - transactions and queries). A background worker using - <literal>BGWORKER_BACKEND_DATABASE_CONNECTION</literal> to connect to - a database must also attach shared memory using - <literal>BGWORKER_SHMEM_ACCESS</literal>, or worker start-up will fail. + capabilities that the module wants. Possible values are: + <variablelist> + + <varlistentry> + <term><literal>BGWORKER_SHMEM_ACCESS</literal></term> + <listitem> + <para> + <indexterm><primary>BGWORKER_SHMEM_ACCESS</primary></indexterm> + Requests shared memory access. This flag is also required to use + lightweight locks (LWlocks). For more information on shared memory access + from bgworkers and extensions see <xref linkend="xfunc-shmem-lwlocks">. + </para> + </listitem> + </varlistentry> + + <varlistentry> + <term><literal>BGWORKER_BACKEND_DATABASE_CONNECTION</literal></term> + <listitem> + <para> + <indexterm><primary>BGWORKER_BACKEND_DATABASE_CONNECTION</primary></indexterm> + Requests the ability to establish a database connection through which it + can later run transactions and queries. A background worker using + <literal>BGWORKER_BACKEND_DATABASE_CONNECTION</literal> to connect to a + database must also attach shared memory using + <literal>BGWORKER_SHMEM_ACCESS</literal>, or worker start-up will fail. + </para> + </listitem> + </varlistentry> + + </variablelist> + </para> + <para> <structfield>bgw_start_time</structfield> is the server state during which <command>postgres</> should start the process; it can be one of @@ -105,58 +132,113 @@ typedef struct BackgroundWorker </para> <para> - <structfield>bgw_main</structfield> is a pointer to the function to run when - the process is started. This function must take a single argument of type - <type>Datum</> and return <type>void</>. - <structfield>bgw_main_arg</structfield> will be passed to it as its only - argument. Note that the global variable <literal>MyBgworkerEntry</literal> - points to a copy of the <structname>BackgroundWorker</structname> structure - passed at registration time. <structfield>bgw_main</structfield> may be - NULL; in that case, <structfield>bgw_library_name</structfield> and - <structfield>bgw_function_name</structfield> will be used to determine - the entry point. This is useful for background workers launched after - postmaster startup, where the postmaster does not have the requisite - library loaded. + <structfield>bgw_main</structfield> specifies the function to run when the + background worker is started. If non-NULL, + <structfield>bgw_main</structfield> will take precedence over + <structfield>bgw_library_name</structfield> and + <structfield>bgw_function_name</structfield>. + <warning> + <para> + Use of this field is deprecated. It should be set to + <literal>NULL</literal> then <structfield>bgw_library_name</structfield> + and <structfield>bgw_function_name</structfield> should be used instead. + </para> + <para> + Specifying the background worker entry point using a function pointer will + not work correctly on Windows (or with <literal>EXEC_BACKEND</literal> + defined). It may also malfunction when used to point to a function in a + dynamically loaded shared library used by a dynamic background worker. + </para> + </warning> </para> <para> <structfield>bgw_library_name</structfield> is the name of a library in which the initial entry point for the background worker should be sought. - It is ignored unless <structfield>bgw_main</structfield> is NULL. - But if <structfield>bgw_main</structfield> is NULL, then the named library - will be dynamically loaded by the worker process and - <structfield>bgw_function_name</structfield> will be used to identify - the function to be called. + The named library will be dynamically loaded by the worker process and + <structfield>bgw_function_name</structfield> will be used to identify the + function to be called. <structfield>bgw_library_name</structfield> is + ignored if <structfield>bgw_main</structfield> is non-NULL. </para> <para> <structfield>bgw_function_name</structfield> is the name of a function in a dynamically loaded library which should be used as the initial entry point - for a new background worker. It is ignored unless + for a new background worker. + + This function must take a single argument of type <type>Datum</> and return + <type>void</>. <structfield>bgw_main_arg</structfield> will be passed to it + as its only argument. It signature is: + + <programlisting> + /* Declaration */ + PGDLLEXPORT extern void bgw_main_func_name(Datum main_arg); + + /* Definition */ + void bgw_main_func_name(Datum main_arg) + { + /* ... */ + } + </programlisting> + + Note that the global variable <literal>MyBgworkerEntry</literal> + points to a copy of the <structname>BackgroundWorker</structname> structure + passed at registration time. <structfield>bgw_main</structfield> should be + NULL; in that case, <structfield>bgw_library_name</structfield> and + <structfield>bgw_function_name</structfield> will be used to determine + the entry point. + + <structfield>bgw_function_name</structfield> is ignored unless <structfield>bgw_main</structfield> is NULL. </para> <para> + <structfield>bgw_main_arg</structfield> is the <type>Datum</> argument + to the background worker main function. It should be set and fetched with + the Datum accessors, e.g. for an integer you should use + <function>Int32GetDatum</function> to set it and + <function>DatumGetInt32</function> to read it. + <warning> + <para> + On Windows (and anywhere else where <literal>EXEC_BACKEND</literal> is + defined) or in dynamic background workers it is not safe to pass a + <type>Datum</> by reference, only by value. If an argument is required is + safest to pass an int32 or other small value and use that as an index into + an array allocated in shared memory. If a value like a <type>cstring</> or + <type>text</type> is passed then the pointer won't be valid from the + postmaster and/or the new background worker process, leading to + crashes or undefined behavour.</para> + </warning> + </para> + + <para> <structfield>bgw_notify_pid</structfield> is the PID of a PostgreSQL backend process to which the postmaster should send <literal>SIGUSR1</> - when the process is started or exits. It should be 0 for workers registered - at postmaster startup time, or when the backend registering the worker does + when the process is started or exits, causing the notified process's latch + to be set. It should be 0 for workers registered + at postmaster startup time, when the backend registering the worker does not wish to wait for the worker to start up. Otherwise, it should be initialized to <literal>MyProcPid</>. </para> <para>Once running, the process can connect to a database by calling + <indexterm><primary>BackgroundWorkerInitializeConnection</primary></indexterm> <function>BackgroundWorkerInitializeConnection(<parameter>char *dbname</parameter>, <parameter>char *username</parameter>)</function> or + <indexterm><primary>BackgroundWorkerInitializeConnectionByOid</primary></indexterm> <function>BackgroundWorkerInitializeConnectionByOid(<parameter>Oid dboid</parameter>, <parameter>Oid useroid</parameter>)</function>. This allows the process to run transactions and queries using the - <literal>SPI</literal> interface. If <varname>dbname</> is NULL or + <link linkend="spi">the Server Programming Interface (<acronym>SPI</acronym>)</link>. See <xref linkend="spi-bgworker"> + for details. If <varname>dbname</> is NULL or <varname>dboid</> is <literal>InvalidOid</>, the session is not connected - to any particular database, but shared catalogs can be accessed. + to any particular database, but shared catalogs (tables where + <varname>relisshared</varname> is <literal>true</literal> in + <varname>pg_class</varname>) can be accessed. If <varname>username</> is NULL or <varname>useroid</> is <literal>InvalidOid</>, the process will run as the superuser created during <command>initdb</>. A background worker can only call one of these two functions, and only - once. It is not possible to switch databases. + once. It is not possible to switch databases without exiting and restarting + the background worker. </para> <para> @@ -224,12 +306,22 @@ typedef struct BackgroundWorker </para> <para> - The <filename>worker_spi</> contrib module contains a working example, - which demonstrates some useful techniques. + Use of <link linkend="spi">the <acronym>SPI</acronym></link> to perform queries and access + database tables in a database-connected background worker requires explicit + management of transactions and snapshots. See <xref linkend="spi-bgworker">. + The same requirements apply to low-level access via direct scans. + </para> + + <para> + The <link linkend="example-worker-spi">worker-spi</link> sample extension + contains a working example of a background worker that uses the + <acronym>SPI</acronym> and shared memory as well as some other useful + techniques. </para> <para> The maximum number of registered background workers is limited by <xref linkend="guc-max-worker-processes">. </para> + </chapter> diff --git a/doc/src/sgml/contrib.sgml b/doc/src/sgml/contrib.sgml index a698d0f..4564274 100644 --- a/doc/src/sgml/contrib.sgml +++ b/doc/src/sgml/contrib.sgml @@ -136,6 +136,7 @@ CREATE EXTENSION <replaceable>module_name</> FROM unpackaged; &seg; &sepgsql; &contrib-spi; + &example-worker-spi; &sslinfo; &tablefunc; &tcn; diff --git a/doc/src/sgml/example-worker-spi.sgml b/doc/src/sgml/example-worker-spi.sgml new file mode 100644 index 0000000..63d8f3d --- /dev/null +++ b/doc/src/sgml/example-worker-spi.sgml @@ -0,0 +1,26 @@ +<!-- doc/src/sgml/example-worker-spi.sgml --> + +<sect1 id="example-worker-spi" xreflabel="worker-spi"> + <title>worker-spi example</title> + + <indexterm zone="example-worker-spi"> + <primary>Background worker with SPI</primary> + <secondary>SPI in background worker</secondary> + </indexterm> + + <para> + The <application>worker-spi</> module provides a complete and working + example of a background worker that uses the SPI to query databases and + uses shared memory for communication. It is not intended for use except + as an example for developers. + </para> + + <para> + It is located in <filename>src/test/modules/worker_spi</filename>. + </para> + + <para> + Relevant documentation for this example module is in <xref linkend="bgworker"/>, <xref linkend="spi"/>, <xref linkend="xfunc"/> and <xref linkend="extend"/>. + </para> + +</sect1> diff --git a/doc/src/sgml/filelist.sgml b/doc/src/sgml/filelist.sgml index f03b72a..7fa1896 100644 --- a/doc/src/sgml/filelist.sgml +++ b/doc/src/sgml/filelist.sgml @@ -142,6 +142,7 @@ <!ENTITY postgres-fdw SYSTEM "postgres-fdw.sgml"> <!ENTITY seg SYSTEM "seg.sgml"> <!ENTITY contrib-spi SYSTEM "contrib-spi.sgml"> +<!ENTITY example-worker-spi SYSTEM "example-worker-spi.sgml"> <!ENTITY sepgsql SYSTEM "sepgsql.sgml"> <!ENTITY sslinfo SYSTEM "sslinfo.sgml"> <!ENTITY tablefunc SYSTEM "tablefunc.sgml"> diff --git a/doc/src/sgml/spi.sgml b/doc/src/sgml/spi.sgml index cb85086..57914be 100644 --- a/doc/src/sgml/spi.sgml +++ b/doc/src/sgml/spi.sgml @@ -10,7 +10,8 @@ <para> The <firstterm>Server Programming Interface</firstterm> (<acronym>SPI</acronym>) gives writers of user-defined - <acronym>C</acronym> functions the ability to run + <acronym>C</acronym> functions and <xref linkend="bgworker"/> + the ability to run <acronym>SQL</acronym> commands inside their functions. <acronym>SPI</acronym> is a set of interface functions to simplify access to the parser, planner, @@ -363,6 +364,7 @@ SPI_execute("INSERT INTO foo SELECT * FROM bar RETURNING *", false, 5); or the command counter, and it allows only plain <command>SELECT</> commands to appear in the command string. The commands are executed using the snapshot previously established for the surrounding query. + Additional steps are required for <xref linkend="spi-bgworker"/>. This execution mode is somewhat faster than the read/write mode due to eliminating per-command overhead. It also allows genuinely <firstterm>stable</> functions to be built: since successive executions @@ -822,7 +824,9 @@ int SPI_execute_with_args(const char *<parameter>command</parameter>, <varlistentry> <term><literal>bool <parameter>read_only</parameter></literal></term> <listitem> - <para><literal>true</> for read-only execution</para> + <para><literal>true</> for read-only execution with no snapshot + or command counter management. See <function>SPI_execute</function> + for details.</para> </listitem> </varlistentry> @@ -3361,7 +3365,8 @@ char * SPI_getnspname(Relation <parameter>rel</parameter>) <quote>upper executor context</quote>, that is, the memory context that was current when <function>SPI_connect</function> was called, which is precisely the right context for a value returned from your - procedure. + procedure. For direct control over the context used for allocation, + <function>MemoryContextAlloc</function> may be used. </para> <para> @@ -4092,6 +4097,143 @@ INSERT INTO a SELECT * FROM a; </para> </sect1> + <sect1 id="spi-bgworker" xreflabel="SPI in background workers"> + <title>Using the SPI from background workers</title> + + <para> + Using the SPI from <link linkend="bgworker">background workers</> + requires some additional steps that are not required from SPI-using + procedures invoked via SQL from normal user backends. When using the SPI + from an SQL-callable function it is safe to assume that a transaction is + already open, there is already a snapshot, and that PostgreSQL's statistics + have been updated. None of these things may be assumed for use of the SPI + from a bgworker. + </para> + + <para> + To safely use the SPI from a bgworker you must ensure that: + <itemizedlist> + <listitem><para>A transaction is open (in progress)</para></listitem> + <listitem><para>The SPI is connected</para></listitem> + <listitem><para>There is an active snapshot or <parameter>read_only</parameter> is set to <literal>false</literal> in SPI calls</para></listitem> + </itemizedlist> + You should also update the statement start and end timestamps for use in + <literal>pg_stat_activity</> using <function>pgstat_report_activity</>. + </para> + + <para> + Attempting to use the SPI without an open transaction or using the SPI + in <parameter>read_only</parameter> mode without setting a snapshot will + generally <emphasis>not</emphasis> cause obvious failures or, in a + <literal>--enable-cassert</literal> build, assertions. Instead it will + usually appear to work for simple cases but may produce incorrect + results or be unstable. Users of background workers should generally + prefix SPI use with +<programlisting> +Assert(IsTransactionState()); +</programlisting> + if the function does not its self establish a transaction. + </para> + + <para> + Typical SPI use from a background worker involves setting up a transaction, + setting the statement start timestamp, connecting to the SPI, updating + pg_stat_activity, establishing a snapshot, running the query/queries, + then performing matching cleanup actions. For example: + </para> + +<programlisting> +const char * some_sql = "SELECT 1;"; + +/* setup */ +StartTransactionCommand(); +SetCurrentStatementStartTimestamp(); +SPI_connect(); +PushActiveSnapshot(GetTransactionSnapshot()); + +pgstat_report_activity(STATE_RUNNING, some_sql); + +/* Run queries with SPI, read_only = false ... */ +spi_ret = SPI_execute(some_sql, false); +if (spi_ret != SPI_OK_TUPLES) + elog(ERROR, "SPI error: %d", spi_ret); + +/* ... process results, run more queries, etc ... */ + +/* cleanup */ +SPI_finish(); +PopActiveSnapshot(); +CommitTransactionCommand(); +pgstat_report_activity(STATE_IDLE, NULL); +</programlisting> + + <para> + In more complex cases the function may need to check if a transaction is + already open with <function>IsTransactionState()</function> and only perform + transaction management if there is no current transaction. If the SPI may + already connected by the caller the function should use + <function>SPI_push_conditional</function> before <function>SPI_connect</function> and + <function>SPI_pop_conditional</function> after <function>SPI_finish</function>. Snapshot + state may also be conditionally handled. The resulting procedure will + look more like: + </para> + +<programlisting> +const char * some_sql = "SELECT 1;"; +bool tx_started = false, + snapshot_pushed = false, + spi_pushed; + +/* setup */ +if (!IsTransactionCommand()) +{ + StartTransactionCommand(); + tx_started = true; +} +SetCurrentStatementStartTimestamp(); +if (!ActiveSnapshotSet()) +{ + PushActiveSnapshot(GetTransactionSnapshot()); + snapshot_pushed = true; +} +spi_pushed = SPI_push_conditional(); +SPI_connect(); + +pgstat_report_activity(STATE_RUNNING, some_sql); + +/* Run queries with SPI, read_only = false... */ +spi_ret = SPI_execute(some_sql, false); +if (spi_ret != SPI_OK_TUPLES) + elog(ERROR, "SPI error: %d", spi_ret); + +/* ... process results, run more queries, etc ... */ + +/* cleanup */ +SPI_finish(); +if (snapshot_pushed) + PopActiveSnapshot(); +SPI_pop_conditional(spi_pushed); +if (tx_started) + CommitTransactionCommand(); +pgstat_report_activity(STATE_IDLE, NULL); +</programlisting> + + <para> + If <parameter>read_only</parameter> is <literal>true</literal> for the SPI + execution functions then the caller should also manage the snapshot using + <function>PushActiveSnapshot</function> and + <function>PopActiveSnapshot</function>. If only <literal>read_only = + false</literal> SPI procedures are used then there is generally no need for + SPI users to explicitly manage snapshots. + </para> + + <para> + See the <xref linkend="example-worker-spi"> module for a more detailed example of + SPI use in background workers. + </para> + +</sect1> + <sect1 id="spi-examples"> <title>Examples</title> @@ -4103,7 +4245,8 @@ INSERT INTO a SELECT * FROM a; that were processed by the command. You can find more complex examples for SPI in the source tree in <filename>src/test/regress/regress.c</filename> and in the - <xref linkend="contrib-spi"> module. + <xref linkend="contrib-spi"> module. For background-worker + specific SPI examples see <xref linkend="spi-bgworker"/>. </para> <programlisting> diff --git a/doc/src/sgml/xfunc.sgml b/doc/src/sgml/xfunc.sgml index 6437ab1..39e6a15 100644 --- a/doc/src/sgml/xfunc.sgml +++ b/doc/src/sgml/xfunc.sgml @@ -3357,6 +3357,60 @@ if (!ptr) } </programlisting> </para> + + <para> + Extensions registered to run at startup + using <xref linkend="guc-shared-preload-libraries"> should instead install a + <literal>shmem_startup_hook</> from <function>_PG_init</>. This will be + invoked once shared memory is ready but before user backends or background + workers get launched. The hook function invoked should use a pattern like + that shown for shared memory initialization above then call the next hook + function, e.g. declare: +<programlisting> +static shmem_startup_hook_type prev_shmem_startup_hook = NULL; +</programlisting> + then from <function>_PG_init</>, after any + <function>RequestAddinShmemSpace</> and <function>RequestAddinLWLocks</> + install the hook: +<programlisting> + prev_shmem_startup_hook = shmem_startup_hook; + shmem_startup_hook = my_worker_shmem_startup; +</programlisting> + where <function>my_worker_shmem_startup</function> is a <type>void</> function + with <type>void</> arguments that calls the next hook (if any): +<programlisting> + if (prev_shmem_startup_hook != NULL) + prev_shmem_startup_hook(); +</programlisting> + then calls <function>ShmemInitStruct</> per the example shown above. An + example of this usage can be found in the initialisation of the <xref + linkend="pgstatstatements"> extension. + </para> + + <caution> + <title>Shared memory is zeroed on postmaster restart</title> + <para> + If the postmaster restarts - usually due to the crash of a backend + process like a user backend or a background worker - then it zeroes + shared memory on restart then re-invokes any shared memory setup hooks + that have been installed by extensions. Extensions using shared memory + must be prepared for this. + </para> + <para> + Background workers are not unregistered if the postmaster restarts + due to the crash of a background worker or user backend. This can lead + to background workers accessing shared memory that has been reinitialized. + Care must be taken to ensure that initialisation of shared memory produces + stable results when re-run or workers must detect the postmaster restart + using a generation counter and exit. In particular if parameters are being + passed to a bgworker via shared memory the background worker + <structfield>bgw_main_arg</structfield> should always be an index into an + array allocated in shared memory, rather than a pointer, and repeated + initialisations of the shared memory segment must produce the same range + of valid indexes in the same order. + </para> + </caution> + </sect2> <sect2 id="extend-Cpp" xreflabel="using C++ for extensibility"> -- 2.1.0
-- Sent via pgsql-docs mailing list (pgsql-docs@postgresql.org) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-docs